home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Comm / term-source.lha / Extras / Source / term-Source.lha / termXPR.c < prev    next >
C/C++ Source or Header  |  1995-07-02  |  58KB  |  2,737 lines

  1. /*
  2. **    termXPR.c
  3. **
  4. **    External transfer protocol support routines
  5. **
  6. **    Copyright © 1990-1995 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* These variables keep the transferred bytes and transfer
  13.      * time in seconds.
  14.      */
  15.  
  16. STATIC LONG         ByteVal,
  17.              ByteMax,
  18.              TimeVal,
  19.              TimeMax,
  20.  
  21.              LastTimeDif,
  22.              LastPercent;
  23.  
  24.     /* Transfer statistics. */
  25.  
  26. STATIC ULONG         CPS_Minimum,
  27.              CPS_Maximum,
  28.              CPS_Average,
  29.              CPS_Current,
  30.              CPS_Count,
  31.              CPS_Last;
  32.  
  33.     LONG         CPL_Min,
  34.              CPL_Avg,
  35.              CPL_Cur;
  36.  
  37.     /* The name of the file being transmitted, in case the
  38.      * `override transfer path' feature is enabled.
  39.      */
  40.  
  41. STATIC struct Buffer    *CurrentFile;
  42.  
  43.     /* Yet another flag, this one determines whether we already told
  44.      * the user that the file we are currently processing will fit
  45.      * on the destination device.
  46.      */
  47.  
  48. STATIC BYTE         Alerted,
  49.              DontWorry,
  50.              TypeChecked,
  51.              ErrorNotified,
  52.              CarrierMessage;
  53.  
  54. STATIC UBYTE __far     RealName[MAX_FILENAME_LENGTH];
  55. STATIC ULONG         LastSeconds;
  56.  
  57.     /* PrintBox(LONG Box,LONG Line,STRPTR String,...):
  58.      *
  59.      *    Update the contents of a text box.
  60.      */
  61.  
  62. STATIC VOID __stdargs
  63. PrintBox(LONG Box,LONG Line,STRPTR String,...)
  64. {
  65.     UBYTE     LocalBuffer[256];
  66.     va_list     VarArgs;
  67.  
  68.     va_start(VarArgs,String);
  69.     VSPrintf(LocalBuffer,String,VarArgs);
  70.     va_end(VarArgs);
  71.  
  72.     LT_SetAttributes(TransferHandle,Box,
  73.         LABX_Index,    Line,
  74.         LABX_Text,    LocalBuffer,
  75.     TAG_DONE);
  76. }
  77.  
  78.     /* OpenTransferWindow():
  79.      *
  80.      *    Local routine to open the transfer window.
  81.      */
  82.  
  83. STATIC BYTE
  84. OpenTransferWindow(VOID)
  85. {
  86.         /* Block window input. */
  87.  
  88.     BlockWindows();
  89.  
  90.         /* Try to open the transfer window panel. */
  91.  
  92.     if(TransferPanel(LocaleString(MSG_TERMXPR_RECEIVE_FILES_TXT)))
  93.     {
  94.             /* Supply the log text. */
  95.  
  96.         LogAction(LocaleString(MSG_TERMXPR_LOGMSG_INITIATE_BINARY_DOWNLOAD_TXT));
  97.  
  98.             /* Return success. */
  99.  
  100.         return(TRUE);
  101.     }
  102.     else
  103.     {
  104.             /* Re-enable window input. */
  105.  
  106.         ReleaseWindows();
  107.  
  108.             /* Return failure. */
  109.  
  110.         return(FALSE);
  111.     }
  112. }
  113.  
  114.     /* CheckAbort(BOOLEAN CheckCarrier):
  115.      *
  116.      *    Check for transfer abort.
  117.      */
  118.  
  119. STATIC LONG __regargs
  120. CheckAbort(BOOLEAN CheckCarrier)
  121. {
  122.     struct IntuiMessage    *Message;
  123.     ULONG             MsgClass,
  124.                  MsgQualifier;
  125.     UWORD             MsgCode;
  126.     struct Gadget        *MsgGadget;
  127.     struct Window        *MsgWindow;
  128.     LONG             Result = 0;
  129.  
  130.         /* No window available for output? */
  131.  
  132.     if(!TransferWindow)
  133.     {
  134.         if(!OpenTransferWindow())
  135.             return(-1);
  136.     }
  137.  
  138.         /* Are we to check the carrier status? */
  139.  
  140.     if(CheckCarrier)
  141.     {
  142.             /* Return error if carrier is lost. */
  143.  
  144.         if(GetSerialStatus() & CIAF_COMCD)
  145.         {
  146.             if(!CarrierMessage)
  147.             {
  148.                 CarrierMessage = TRUE;
  149.  
  150.                 AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_CARRIER_LOST_TXT));
  151.             }
  152.  
  153.             ObtainSemaphore(&OnlineSemaphore);
  154.  
  155.             if(Online)
  156.             {
  157.                 WasOnline    = Online;
  158.                 Online        = FALSE;
  159.             }
  160.  
  161.             ReleaseSemaphore(&OnlineSemaphore);
  162.  
  163.             TransferError = TRUE;
  164.  
  165.             return(-1);
  166.         }
  167.     }
  168.  
  169.         /* Process all incoming messages. */
  170.  
  171.     while(Message = (struct IntuiMessage *)GT_GetIMsg(TransferWindow -> UserPort))
  172.     {
  173.         MsgClass    = Message -> Class;
  174.         MsgQualifier    = Message -> Qualifier;
  175.         MsgCode        = Message -> Code;
  176.         MsgGadget    = (struct Gadget *)Message -> IAddress;
  177.         MsgWindow    = Message -> IDCMPWindow;
  178.  
  179.         GT_ReplyIMsg(Message);
  180.  
  181.         if(MsgWindow == TransferWindow)
  182.         {
  183.             if(!Result)
  184.             {
  185.                 LT_HandleInput(TransferHandle,MsgQualifier,&MsgClass,&MsgCode,&MsgGadget);
  186.  
  187.                 if(MsgClass == IDCMP_CLOSEWINDOW)
  188.                 {
  189.                     LogAction(LocaleString(MSG_TERMXPR_LOGMSG_TRANSFER_ABORTED_TXT));
  190.  
  191.                     TransferAborted = TRUE;
  192.  
  193.                     Result = -1;
  194.                 }
  195.  
  196.                 if(MsgClass == IDCMP_GADGETUP)
  197.                 {
  198.                     switch(MsgGadget -> GadgetID)
  199.                     {
  200.                         case GAD_TRANSFER_ABORT:
  201.  
  202.                             LogAction(LocaleString(MSG_TERMXPR_LOGMSG_TRANSFER_ABORTED_TXT));
  203.  
  204.                             TransferAborted = TRUE;
  205.  
  206.                             Result = -1;
  207.  
  208.                             break;
  209.  
  210.                         case GAD_TRANSFER_SKIP:
  211.  
  212.                             LogAction(LocaleString(MSG_TERMXPR_LOGMSG_FILE_SKIPPED_TXT));
  213.  
  214.                             Result = 1;
  215.  
  216.                             break;
  217.  
  218.                         case GAD_TRANSFER_ABORT_FILE:
  219.  
  220.                             LogAction(LocaleString(MSG_TERMXPR_LOGMSG_FILE_ABORTED_TXT));
  221.  
  222.                             Result = 2;
  223.  
  224.                             break;
  225.                     }
  226.                 }
  227.             }
  228.         }
  229.         else
  230.         {
  231.             if(TransferPerfWindow)
  232.             {
  233.                 struct RastPort *RPort = TransferPerfWindow -> RPort;
  234.  
  235.                 if(MsgClass == IDCMP_NEWSIZE)
  236.                 {
  237.                     SetAPen(RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
  238.  
  239.                     RectFill(RPort,TransferPerfWindow -> BorderLeft,TransferPerfWindow -> BorderTop,TransferPerfWindow -> Width - (TransferPerfWindow -> BorderRight + 1),TransferPerfWindow -> Height - (TransferPerfWindow -> BorderBottom + 1));
  240.  
  241.                     CPL_Min = CPL_Avg = CPL_Cur = -1;
  242.                 }
  243.  
  244.                 if(MsgClass == IDCMP_CLOSEWINDOW)
  245.                 {
  246.                     PutWindowInfo(WINDOW_PERF,TransferPerfWindow -> LeftEdge,TransferPerfWindow -> TopEdge,TransferPerfWindow -> Width,TransferPerfWindow -> Height);
  247.  
  248.                     CloseWindowSafely(TransferPerfWindow);
  249.  
  250.                     TransferPerfWindow = NULL;
  251.                 }
  252.             }
  253.         }
  254.     }
  255.  
  256.     return(Result);
  257. }
  258.  
  259.     /* NewFileName(STRPTR Source,STRPTR Buffer):
  260.      *
  261.      *    Build a valid file and path name, including path
  262.      *    substitution, etc.
  263.      */
  264.  
  265. STATIC STRPTR __regargs
  266. NewFileName(STRPTR Source,STRPTR Buffer)
  267. {
  268.     if(Config -> TransferConfig -> OverridePath && !Uploading)
  269.     {
  270.         if(DownloadPath)
  271.             strcpy(Buffer,DownloadPath);
  272.         else
  273.             strcpy(Buffer,Config -> PathConfig -> BinaryDownloadPath);
  274.  
  275.         if(!Buffer[0])
  276.         {
  277.             if(!GetCurrentDirName(Buffer,MAX_FILENAME_LENGTH))
  278.                 Buffer[0] = 0;
  279.         }
  280.  
  281.         if(Buffer[0])
  282.         {
  283.             if(AddPart(Buffer,FilePart(Source),MAX_FILENAME_LENGTH))
  284.                 return(Buffer);
  285.         }
  286.     }
  287.     else
  288.     {
  289.         if(FilePart(Source) == Source)
  290.         {
  291.             if(GetCurrentDirName(Buffer,MAX_FILENAME_LENGTH))
  292.             {
  293.                 if(AddPart(Buffer,Source,MAX_FILENAME_LENGTH))
  294.                     return(Buffer);
  295.             }
  296.         }
  297.     }
  298.  
  299.     strcpy(Buffer,Source);
  300.  
  301.     return(Source);
  302. }
  303.  
  304.     /* IdentifySource(STRPTR Name,STRPTR BBSName,struct DateStamp *OpenDate):
  305.      *
  306.      *    Attach source information (BBS name, date and time) to a file.
  307.      */
  308.  
  309. STATIC VOID __regargs
  310. IdentifySource(STRPTR Name,STRPTR BBSName,struct DateStamp *OpenDate)
  311. {
  312.     UBYTE        LocalBuffer[MAX_FILENAME_LENGTH],
  313.             Time[40],
  314.             Date[40];
  315.     struct DateTime    DateTime;
  316.  
  317.     CopyMem(OpenDate,&DateTime . dat_Stamp,sizeof(struct DateStamp));
  318.  
  319.         /* Prepare for date conversion. */
  320.  
  321.     DateTime . dat_Format    = FORMAT_DOS;
  322.     DateTime . dat_Flags    = 0;
  323.     DateTime . dat_StrDay    = NULL;
  324.     DateTime . dat_StrDate    = Date;
  325.     DateTime . dat_StrTime    = Time;
  326.  
  327.         /* Convert the date. */
  328.  
  329.     if(DateToStr(&DateTime))
  330.     {
  331.         StripSpaces(BBSName);
  332.         StripSpaces(Date);
  333.         StripSpaces(Time);
  334.  
  335.         if(BBSName[0])
  336.             SPrintf(LocalBuffer,"%s %s %s",BBSName,Date,Time);
  337.         else
  338.             SPrintf(LocalBuffer,"%s %s",Date,Time);
  339.  
  340.         SetComment(Name,LocalBuffer);
  341.     }
  342. }
  343.  
  344.     /* GetSeconds(STRPTR String):
  345.      *
  346.      *    Tries to turn a string of the format hh:mm:ss into
  347.      *    an integer number.
  348.      */
  349.  
  350. STATIC LONG __regargs
  351. GetSeconds(STRPTR String)
  352. {
  353.     UBYTE    Buffer[20];
  354.     LONG    Seconds = 0;
  355.  
  356.     memset(Buffer,0,20);
  357.  
  358.     strcpy(Buffer,String);
  359.  
  360.     Seconds += Atol(&Buffer[6]);
  361.  
  362.     Buffer[5] = 0;
  363.  
  364.     Seconds += Atol(&Buffer[3]) * 60;
  365.  
  366.     Buffer[2] = 0;
  367.  
  368.     Seconds += Atol(&Buffer[0]) * 3600;
  369.  
  370.     return(Seconds);
  371. }
  372.  
  373.     /* TruncateName(STRPTR FileName):
  374.      *
  375.      *    Truncates a file name to a maximum of 48 characters.
  376.      */
  377.  
  378. STATIC STRPTR __regargs
  379. TruncateName(STRPTR FileName)
  380. {
  381.     WORD Len = strlen(FileName);
  382.  
  383.     if(Len > 48)
  384.     {
  385.         WORD i;
  386.  
  387.         for(i = Len - 48 ; i < Len ; i++)
  388.         {
  389.             if(i >= Len - 44 && FileName[i] == '/')
  390.             {
  391.                 STATIC UBYTE __far NameBuffer[MAX_FILENAME_LENGTH];
  392.  
  393.                 strcpy(NameBuffer,".../");
  394.  
  395.                 strcat(NameBuffer,&FileName[i + 1]);
  396.  
  397.                 return(NameBuffer);
  398.             }
  399.         }
  400.     }
  401.  
  402.     return(FileName);
  403. }
  404.  
  405.     /* IsBlockMappedDevice(struct MsgPort *Handler):
  406.      *
  407.      *    See if the lock given points to a block mapped filing
  408.      *    system.
  409.      */
  410.  
  411. STATIC BOOL __regargs
  412. IsBlockMappedDevice(struct MsgPort *Handler)
  413. {
  414.     struct DosList    *Entry;
  415.     BOOL         IsBlockMapped = FALSE;
  416.  
  417.         // Find the device the lock belongs to
  418.  
  419.     if(Entry = LockDosList(LDF_DEVICES | LDF_READ))
  420.     {
  421.         while(Entry = NextDosEntry(Entry,LDF_DEVICES))
  422.         {
  423.             if(Entry -> dol_Task == Handler)
  424.             {
  425.                 struct FileSysStartupMsg *Startup = (struct FileSysStartupMsg *)BADDR(Entry -> dol_misc . dol_handler . dol_Startup);
  426.  
  427.                     // Plain filing system usually don't
  428.                     // use the startup entry
  429.  
  430.                 if(TypeOfMem(Startup))
  431.                 {
  432.                     STRPTR         Name        = (STRPTR)BADDR(Startup -> fssm_Device);
  433.                     struct DosEnvec    *Environ    = (struct DosEnvec *)BADDR(Startup -> fssm_Environ);
  434.  
  435.                         // Valid data in the startup entry?
  436.  
  437.                     if(TypeOfMem(Name) && TypeOfMem(Environ))
  438.                     {
  439.                         struct IOStdReq __aligned Request;
  440.  
  441.                         memset(&Request,0,sizeof(struct IOStdReq));
  442.  
  443.                             // Last chance, try to open the device driver
  444.  
  445.                         if(!OpenDevice(Name + 1,Startup -> fssm_Unit,&Request,Startup -> fssm_Flags))
  446.                         {
  447.                                 // This is a block mapped filing system
  448.  
  449.                             IsBlockMapped = TRUE;
  450.  
  451.                             CloseDevice(&Request);
  452.  
  453.                             break;
  454.                         }
  455.                     }
  456.                 }
  457.             }
  458.         }
  459.  
  460.         UnLockDosList(LDF_DEVICES | LDF_READ);
  461.     }
  462.  
  463.     return(IsBlockMapped);
  464. }
  465.  
  466.     /* CalculateBlocks(LONG Size,LONG BlockSize):
  467.      *
  468.      *    Calculate the number of blocks a file will
  469.      *    occupy if saved to a disk.
  470.      */
  471.  
  472. STATIC LONG __regargs
  473. CalculateBlocks(LONG Size,LONG BlockSize)
  474. {
  475.     LONG    Blocks        = 1;        /* One for the file header. */
  476.     BYTE    HasExtension    = FALSE,    /* No extension block yet. */
  477.         Extension    = 0;        /* How many block pointers yet. */
  478.  
  479.         /* Round to next block. */
  480.  
  481.     Size = ((Size + BlockSize - 1) / BlockSize) * BlockSize;
  482.  
  483.     while(Size)
  484.     {
  485.             /* Add another block. */
  486.  
  487.         Blocks++;
  488.  
  489.             /* Subtract another block. */
  490.  
  491.         Size -= BlockSize;
  492.  
  493.             /* Add another block pointer, if 72 have been
  494.              * added, add another extension block.
  495.              */
  496.  
  497.         if((Extension++) == 72)
  498.         {
  499.                 /* If no extension block has been generated
  500.                  * yet, we were running on the block pointers
  501.                  * of the file header itself.
  502.                  */
  503.  
  504.             if(!HasExtension)
  505.                 HasExtension = TRUE;
  506.             else
  507.                 Blocks++;
  508.  
  509.                 /* Reset extension block counter. */
  510.  
  511.             Extension = 0;
  512.         }
  513.     }
  514.  
  515.     return(Blocks);
  516. }
  517.  
  518.     /* GetOptionMode(struct xpr_option *Option):
  519.      *
  520.      *    Turn text into a boolean value.
  521.      */
  522.  
  523. STATIC BYTE __regargs
  524. GetOptionMode(struct xpr_option *Option)
  525. {
  526.     if(Option)
  527.     {
  528.         STATIC STRPTR TrueOptions[] =
  529.         {
  530.             "ON",
  531.             "TRUE",
  532.             "T",
  533.             "YES",
  534.             "Y",
  535.             NULL
  536.         };
  537.  
  538.         register WORD i;
  539.  
  540.         for(i = 0 ; TrueOptions[i] ; i++)
  541.         {
  542.             if(!Stricmp(Option -> xpro_value,TrueOptions[i]))
  543.                 return(TRUE);
  544.         }
  545.     }
  546.  
  547.     return(FALSE);
  548. }
  549.  
  550.     /* SerialErrorReport(struct IOExtSer *Request):
  551.      *
  552.      *    Report a certain I/O error cause.
  553.      */
  554.  
  555. STATIC BYTE __regargs
  556. SerialErrorReport(struct IOExtSer *Request)
  557. {
  558.     STRPTR    ErrorMessage;
  559.     BYTE    IsFatal;
  560.  
  561.     switch(Request -> IOSer . io_Error)
  562.     {
  563.         case SerErr_LineErr:
  564.  
  565.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_HARDWARE_DATA_OVERRUN_TXT);
  566.  
  567.             IsFatal = FALSE;
  568.  
  569.             break;
  570.  
  571.         case SerErr_ParityErr:
  572.  
  573.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_PARITY_ERROR_TXT);
  574.  
  575.             IsFatal = TRUE;
  576.  
  577.             break;
  578.  
  579.         case SerErr_TimerErr:
  580.  
  581.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_TIMER_ERROR_TXT);
  582.  
  583.             IsFatal = FALSE;
  584.  
  585.             break;
  586.  
  587.         case SerErr_BufOverflow:
  588.  
  589.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_READ_BUFFER_OVERFLOWED_TXT);
  590.  
  591.             IsFatal = FALSE;
  592.  
  593.             break;
  594.  
  595.         case SerErr_NoDSR:
  596.  
  597.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_NO_DSR_TXT);
  598.  
  599.             IsFatal = TRUE;
  600.  
  601.             break;
  602.  
  603.         case SerErr_DetectedBreak:
  604.  
  605.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_BREAK_DETECTED_TXT);
  606.  
  607.             IsFatal = TRUE;
  608.  
  609.             break;
  610.  
  611.         default:
  612.  
  613.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_UNKNOWN_CAUSE_TXT);
  614.  
  615.             IsFatal = FALSE;
  616.  
  617.             break;
  618.     }
  619.  
  620.     AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_ERROR_TEMPLATE_TXT),Request -> IOSer . io_Error,ErrorMessage);
  621.  
  622.     if(IsFatal)
  623.     {
  624.         TransferError = TRUE;
  625.  
  626.         return(TRUE);
  627.     }
  628.     else
  629.         return(FALSE);
  630. }
  631.  
  632.     /* xpr_fopen(STRPTR FileName,STRPTR AccessMode):
  633.      *
  634.      *    Open a file for random access.
  635.      */
  636.  
  637. LONG __saveds __asm
  638. xpr_fopen(register __a0 STRPTR FileName,register __a1 STRPTR AccessMode)
  639. {
  640.     UBYTE         RealName[MAX_FILENAME_LENGTH];
  641.     struct Buffer    *File;
  642.  
  643.     DB(kprintf("xpr_fopen(\"%s\",\"%s\")\n",FileName,AccessMode));
  644.  
  645.     Alerted = CarrierMessage = ErrorNotified = DontWorry = TypeChecked = FALSE;
  646.  
  647.         /* Reset transfer counters. */
  648.  
  649.     ByteVal = ByteMax = TimeVal = TimeMax = LastTimeDif = 0;
  650.  
  651.     LastPercent = -1;
  652.  
  653.         /* Reset CPS statistics. */
  654.  
  655.     CPS_Minimum    = (ULONG)~0;
  656.     CPS_Maximum    = 0;
  657.     CPS_Average    = 0;
  658.     CPS_Current    = 0;
  659.     CPS_Count    = 0;
  660.     CPS_Last    = 0;
  661.  
  662.         /* No window available for output? */
  663.  
  664.     if(!TransferWindow)
  665.         OpenTransferWindow();
  666.  
  667.     if(OriginalName[0])
  668.     {
  669.         if(!Stricmp(ShrunkenName,FileName))
  670.             FileName = OriginalName;
  671.     }
  672.  
  673.         /* Determine the file name. */
  674.  
  675.     FileName = NewFileName(FileName,RealName);
  676.  
  677.         /* Determine file transfer mode... */
  678.  
  679.     if(File = BufferOpen(FileName,AccessMode))
  680.     {
  681.         switch(AccessMode[0])
  682.         {
  683.             case 'r':
  684.  
  685.                 LogAction(LocaleString(MSG_TERMXPR_LOGMSG_SEND_FILE_TXT),FileName);
  686.                 break;
  687.  
  688.             case 'w':
  689.  
  690.                 LogAction(LocaleString(MSG_TERMXPR_LOGMSG_RECEIVE_FILE_TXT),FileName);
  691.                 break;
  692.  
  693.             case 'a':
  694.  
  695.                 LogAction(LocaleString(MSG_TERMXPR_LOGMSG_UPDATE_FILE_TXT),FileName);
  696.                 break;
  697.         }
  698.  
  699.         CurrentFile = File;
  700.     }
  701.  
  702.     DidTransfer = TRUE;
  703.  
  704.     return((LONG)File);
  705. }
  706.  
  707.     /* xpr_fclose(struct Buffer *File):
  708.      *
  709.      *    Close a file opened by xpr_fopen.
  710.      */
  711.  
  712. LONG __saveds __asm
  713. xpr_fclose(register __a0 struct Buffer *File)
  714. {
  715.     UBYTE            RealName[MAX_FILENAME_LENGTH];
  716.     struct DateStamp    OpenDate;
  717.     BYTE            WriteAccess,
  718.                 Used;
  719.  
  720.     DB(kprintf("xpr_fclose(0x%08lx)\n",File));
  721.  
  722.         /* This happened only once so far, but... */
  723.  
  724.     if(!File)
  725.     {
  726.         CurrentFile = NULL;
  727.  
  728.         return(1);
  729.     }
  730.  
  731.         /* Save some information. */
  732.  
  733.     OpenDate    = File -> OpenDate;
  734.     WriteAccess    = File -> WriteAccess;
  735.     Used        = File -> Used;
  736.  
  737.         /* Get the name of the file. */
  738.  
  739.     if(!NameFromFH(File -> FileHandle,RealName,MAX_FILENAME_LENGTH))
  740.         RealName[0] = 0;
  741.  
  742.         /* Close the file and see what it brings... */
  743.  
  744.     if(BufferClose(File) && RealName[0])
  745.     {
  746.             /* Did any access take place at all?
  747.              * xprzmodem.library for example just
  748.              * opens and closes a file in order to
  749.              * see if it exists.
  750.              */
  751.  
  752.         if(!Used)
  753.             LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_TXT),RealName);
  754.         else
  755.         {
  756.                 /* Did we receive or send a file? */
  757.  
  758.             if(WriteAccess)
  759.             {
  760.                 LONG Size;
  761.  
  762.                     /* Did the file remain empty? */
  763.  
  764.                 if(!(Size = GetFileSize(RealName)))
  765.                 {
  766.                     AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_FILE_REMOVED_TXT),FilePart(RealName));
  767.  
  768.                         /* Delete empty file. */
  769.  
  770.                     if(DeleteFile(RealName))
  771.                         LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_REMOVED_TXT),RealName);
  772.                     else
  773.                         LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_TXT),RealName);
  774.                 }
  775.                 else
  776.                 {
  777.                     struct Node *SomeNode;
  778.  
  779.                     if(ByteMax)
  780.                     {
  781.                         if(Size >= ByteMax)
  782.                             AddTransferInfo(FALSE,LocaleString(MSG_TERMXPR_FILE_RECEIVED_TXT),FilePart(RealName));
  783.                         else
  784.                             AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_INCOMPLETE_FILE_RECEIVED_TXT),FilePart(RealName));
  785.                     }
  786.  
  787.                         /* Try to identify the file type. */
  788.  
  789.                     switch(Config -> TransferConfig -> IdentifyFiles)
  790.                     {
  791.                         case IDENTIFY_IGNORE:
  792.  
  793.                             if(Config -> MiscConfig -> CreateIcons)
  794.                                 Identify(RealName,FALSE);
  795.  
  796.                             break;
  797.  
  798.                         case IDENTIFY_FILETYPE:
  799.  
  800.                             Identify(RealName,TRUE);
  801.                             break;
  802.  
  803.                         case IDENTIFY_SOURCE:
  804.  
  805.                             IdentifySource(RealName,CurrentBBSName,&OpenDate);
  806.  
  807.                             if(Config -> MiscConfig -> CreateIcons)
  808.                                 Identify(RealName,FALSE);
  809.  
  810.                             break;
  811.                     }
  812.  
  813.                     if(CPS_Minimum == (ULONG)~0)
  814.                         CPS_Minimum = 0;
  815.  
  816.                     if(CPS_Count == 0)
  817.                     {
  818.                         CPS_Average    = 0;
  819.                         CPS_Count    = 1;
  820.                     }
  821.  
  822.                     LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_BYTES_TXT),RealName,Size,CPS_Minimum,CPS_Average / CPS_Count,CPS_Maximum);
  823.  
  824.                     if(SomeNode = CreateGenericListNode(0,RealName))
  825.                         AddGenericListNode(GenericListTable[GLIST_DOWNLOAD],SomeNode,ADD_GLIST_BOTTOM);
  826.                 }
  827.             }
  828.             else
  829.             {
  830.                     /* Set the archived bit on files we uploaded? */
  831.  
  832.                 if(Config -> TransferConfig -> SetArchivedBit)
  833.                 {
  834.                     struct FileInfoBlock *FileInfo;
  835.  
  836.                     if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
  837.                     {
  838.                         BPTR FileLock;
  839.  
  840.                             /* Get a lock on it. */
  841.  
  842.                         if(FileLock = Lock(RealName,ACCESS_READ))
  843.                         {
  844.                                 /* Examine the file. */
  845.  
  846.                             if(Examine(FileLock,FileInfo))
  847.                             {
  848.                                     /* Remove the lock. */
  849.  
  850.                                 UnLock(FileLock);
  851.  
  852.                                     /* Set the `archived' bit. */
  853.  
  854.                                 SetProtection(RealName,FileInfo -> fib_Protection | FIBF_ARCHIVE);
  855.                             }
  856.                             else
  857.                                 UnLock(FileLock);
  858.                         }
  859.  
  860.                         FreeDosObject(DOS_FIB,FileInfo);
  861.                     }
  862.                 }
  863.  
  864.                 AddTransferInfo(FALSE,LocaleString(MSG_TERMXPR_FILE_SENT_TXT),FilePart(RealName));
  865.  
  866.                 LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_TXT),RealName);
  867.  
  868.                 RemoveUploadListItem(RealName);
  869.             }
  870.         }
  871.     }
  872.  
  873.     CurrentFile = NULL;
  874.  
  875.     return(1);
  876. }
  877.  
  878.     /* xpr_fread(APTR Buffer,LONG Size,LONG Count,struct Buffer *File):
  879.      *
  880.      *    Read a few bytes from a file.
  881.      */
  882.  
  883. LONG __saveds __asm
  884. xpr_fread(register __a0 APTR Buffer,register __d0 LONG Size,register __d1 LONG Count,register __a1 struct Buffer *File)
  885. {
  886.     DB(kprintf("xpr_fread(0x%08lx,%ld,%ld,0x%08lx)\n",Buffer,Size,Count,File));
  887.  
  888.     return(BufferRead(File,Buffer,Size * Count) / Size);
  889. }
  890.  
  891.     /* xpr_fwrite(APTR Buffer,LONG Size,LONG Count,struct Buffer *File):
  892.      *
  893.      *    Write a few bytes to a file.
  894.      */
  895.  
  896. LONG __saveds __asm
  897. xpr_fwrite(register __a0 APTR Buffer,register __d0 LONG Size,register __d1 LONG Count,register __a1 struct Buffer *File)
  898. {
  899.     DB(kprintf("xpr_fwrite(0x%08lx,%ld,%ld,0x%08lx)\n",Buffer,Size,Count,File));
  900.  
  901.     return(BufferWrite(File,Buffer,Size * Count) / Size);
  902. }
  903.  
  904.     /* xpr_fseek(struct Buffer *File,LONG Offset,LONG Origin):
  905.      *
  906.      *    Move the read/write pointer in a file.
  907.      */
  908.  
  909. LONG __saveds __asm
  910. xpr_fseek(register __a0 struct Buffer *File,register __d0 LONG Offset,register __d1 LONG Origin)
  911. {
  912.     DB(kprintf("xpr_fseek(0x%08lx,%ld,%ld)\n",File,Offset,Origin));
  913.  
  914.     return(BufferSeek(File,Offset,Origin) ? 0 : -1);
  915. }
  916.  
  917.     /* xpr_sread(APTR Buffer,LONG Size,LONG Timeout):
  918.      *
  919.      *    Read a few bytes from the serial port (including
  920.      *    timeouts).
  921.      */
  922.  
  923. LONG __saveds __asm
  924. xpr_sread(register __a0 APTR Buffer,register __d0 LONG Size,register __d1 ULONG Timeout)
  925. {
  926.     DB(kprintf("xpr_sread(0x%08lx,%ld,%ld)\n",Buffer,Size,Timeout));
  927.  
  928.         /* No window available for output? */
  929.  
  930.     if(!TransferWindow)
  931.     {
  932.         if(!OpenTransferWindow())
  933.             return(-1);
  934.     }
  935.  
  936.         /* Are both IORequests available? */
  937.  
  938.     if(WriteRequest && ReadRequest)
  939.     {
  940.             /* Valid size parameter? */
  941.  
  942.         if(Size > 0)
  943.         {
  944.             ULONG    Waiting;
  945.             UWORD    Status;
  946.  
  947.             GetSerialInfo(&Waiting,&Status);
  948.  
  949.                 /* Return error if carrier is lost. */
  950.  
  951.             if(Config -> SerialConfig -> CheckCarrier && !Config -> SerialConfig -> DirectConnection)
  952.             {
  953.                 if(Status & CIAF_COMCD)
  954.                 {
  955.                     if(!CarrierMessage)
  956.                     {
  957.                         CarrierMessage = TRUE;
  958.  
  959.                         AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_CARRIER_LOST_TXT));
  960.                     }
  961.  
  962.                     ObtainSemaphore(&OnlineSemaphore);
  963.  
  964.                     if(Online)
  965.                     {
  966.                         WasOnline    = Online;
  967.                         Online        = FALSE;
  968.                     }
  969.  
  970.                     ReleaseSemaphore(&OnlineSemaphore);
  971.  
  972.                     TransferError = TRUE;
  973.  
  974.                     return(-1);
  975.                 }
  976.             }
  977.  
  978.             /* ALWAYS */
  979.             {
  980.                 if(Waiting)
  981.                 {
  982.                         /* No timeout specified? Read as many
  983.                          * bytes as available.
  984.                          */
  985.  
  986.                     if(!Timeout)
  987.                     {
  988.                         if(Waiting > Size)
  989.                             Waiting = Size;
  990.  
  991.                         if(DoSerialRead(Buffer,Waiting))
  992.                         {
  993.                             if(SerialErrorReport(ReadRequest))
  994.                                 return(-1);
  995.                             else
  996.                                 Waiting = ReadRequest -> IOSer . io_Actual;
  997.                         }
  998.  
  999.                         BytesIn += Waiting;
  1000.  
  1001.                         return((LONG)Waiting);
  1002.                     }
  1003.  
  1004.                         /* Enough data pending to be read? */
  1005.  
  1006.                     if(Waiting >= Size)
  1007.                     {
  1008.                         if(DoSerialRead(Buffer,Size))
  1009.                         {
  1010.                             if(SerialErrorReport(ReadRequest))
  1011.                                 return(-1);
  1012.                             else
  1013.                                 Size = ReadRequest -> IOSer . io_Actual;
  1014.                         }
  1015.  
  1016.                         BytesIn += Size;
  1017.  
  1018.                         return(Size);
  1019.                     }
  1020.                 }
  1021.                 else
  1022.                 {
  1023.                         /* No timeout & no bytes available:
  1024.                          * return immediately.
  1025.                          */
  1026.  
  1027.                     if(!Timeout)
  1028.                         return(0);
  1029.                 }
  1030.             }
  1031.  
  1032.             /* ALWAYS */
  1033.             {
  1034.                 register ULONG    SignalSet,
  1035.                         SerialMask = PORTMASK(ReadPort),
  1036.                         WindowMask = PORTMASK(TransferWindow -> UserPort);
  1037.  
  1038.                     /* Set up the timer. */
  1039.  
  1040.                 TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  1041.                 TimeRequest -> tr_time . tv_secs    = Timeout / MILLION;
  1042.                 TimeRequest -> tr_time . tv_micro    = Timeout % MILLION;
  1043.  
  1044.                     /* Prevent early termination. */
  1045.  
  1046.                 ClrSignal(SerialMask | SIG_TIMER);
  1047.  
  1048.                     /* Start IO... */
  1049.  
  1050.                 SendIO(TimeRequest);
  1051.  
  1052.                     /* Set up the read request. */
  1053.  
  1054.                 StartSerialRead(Buffer,Size);
  1055.  
  1056.                 FOREVER
  1057.                 {
  1058.                     SignalSet = Wait(SerialMask | SIG_TIMER | WindowMask);
  1059.  
  1060.                         /* Abort file transfer? */
  1061.  
  1062.                     if(SignalSet & WindowMask)
  1063.                     {
  1064.                         LONG Result = CheckAbort(FALSE);
  1065.  
  1066.                             /* Let's get out of here
  1067.                              * and hope that the protocol
  1068.                              * will call xpr_chkabort()
  1069.                              * in time.
  1070.                              */
  1071.  
  1072.                         if(Result)
  1073.                         {
  1074.                             if(TransferAbortState != Result)
  1075.                                 TransferAbortState = Result;
  1076.  
  1077.                                 /* Does the user want to cancel
  1078.                                  * the transmission?
  1079.                                  */
  1080.  
  1081.                             if(Result < 0)
  1082.                             {
  1083.                                     // Do it the hard way
  1084.  
  1085.                                 if(TransferAbortCount++)
  1086.                                 {
  1087.                                     StopSerialRead();
  1088.  
  1089.                                     if(!CheckIO(TimeRequest))
  1090.                                         AbortIO(TimeRequest);
  1091.  
  1092.                                     WaitIO(TimeRequest);
  1093.  
  1094.                                         // Oh Janet, don't tell me to can it
  1095.  
  1096.                                     DoSerialWrite(ZModemCancel,20);
  1097.  
  1098.                                     return(Result);
  1099.                                 }
  1100.                             }
  1101.  
  1102.                                 /* Abort the read request. */
  1103.  
  1104.                             StopSerialRead();
  1105.  
  1106.                                 /* Remove the timer request. */
  1107.  
  1108.                             if(!CheckIO(TimeRequest))
  1109.                                 AbortIO(TimeRequest);
  1110.  
  1111.                             WaitIO(TimeRequest);
  1112.  
  1113.                                 /* Did the driver receive any
  1114.                                  * data?
  1115.                                  */
  1116.  
  1117.                             if(ReadRequest -> IOSer . io_Actual)
  1118.                             {
  1119.                                 BytesIn += ReadRequest -> IOSer . io_Actual;
  1120.  
  1121.                                 return((LONG)ReadRequest -> IOSer . io_Actual);
  1122.                             }
  1123.                             else
  1124.                             {
  1125.                                     /* Take a second look and query the number of
  1126.                                      * bytes ready to be received, there may
  1127.                                      * still be some bytes in the buffer.
  1128.                                      * Note: this depends on the way the
  1129.                                      * driver handles read abort.
  1130.                                      */
  1131.  
  1132.                                 Waiting = GetSerialWaiting();
  1133.  
  1134.                                     /* Don't read too much. */
  1135.  
  1136.                                 if(Size > Waiting)
  1137.                                     Size = Waiting;
  1138.  
  1139.                                     /* Are there any bytes to be transferred? */
  1140.  
  1141.                                 if(Size)
  1142.                                 {
  1143.                                         /* Read the data. */
  1144.  
  1145.                                     if(DoSerialRead(Buffer,Size))
  1146.                                     {
  1147.                                         if(SerialErrorReport(ReadRequest))
  1148.                                             return(-1);
  1149.                                         else
  1150.                                             Size = ReadRequest -> IOSer . io_Actual;
  1151.                                     }
  1152.  
  1153.                                     BytesIn += Size;
  1154.                                 }
  1155.  
  1156.                                 return(Size);
  1157.                             }
  1158.                         }
  1159.                     }
  1160.  
  1161.                         /* Receive buffer filled? */
  1162.  
  1163.                     if(SignalSet & SerialMask)
  1164.                     {
  1165.                             /* Abort the timer request. */
  1166.  
  1167.                         if(!CheckIO(TimeRequest))
  1168.                             AbortIO(TimeRequest);
  1169.  
  1170.                         WaitIO(TimeRequest);
  1171.  
  1172.                             /* Did the request terminate gracefully? */
  1173.  
  1174.                         if(WaitSerialRead())
  1175.                         {
  1176.                             if(SerialErrorReport(ReadRequest))
  1177.                                 return(-1);
  1178.                             else
  1179.                                 Size = ReadRequest -> IOSer . io_Actual;
  1180.                         }
  1181.  
  1182.                         BytesIn += Size;
  1183.  
  1184.                         return(Size);
  1185.                     }
  1186.  
  1187.                         /* Hit by timeout? */
  1188.  
  1189.                     if(SignalSet & SIG_TIMER)
  1190.                     {
  1191.                             /* Abort the read request. */
  1192.  
  1193.                         StopSerialRead();
  1194.  
  1195.                             /* Remove the timer request. */
  1196.  
  1197.                         WaitIO(TimeRequest);
  1198.  
  1199.                             /* Did the driver receive any
  1200.                              * data?
  1201.                              */
  1202.  
  1203.                         if(ReadRequest -> IOSer . io_Actual)
  1204.                         {
  1205.                             BytesIn += ReadRequest -> IOSer . io_Actual;
  1206.  
  1207.                             return((LONG)ReadRequest -> IOSer . io_Actual);
  1208.                         }
  1209.                         else
  1210.                         {
  1211.                                 /* Take a second look and query the number of
  1212.                                  * bytes ready to be received, there may
  1213.                                  * still be some bytes in the buffer.
  1214.                                  * Note: this depends on the way the
  1215.                                  * driver handles read abort.
  1216.                                  */
  1217.  
  1218.                             Waiting = GetSerialWaiting();
  1219.  
  1220.                                 /* Don't read too much. */
  1221.  
  1222.                             if(Size > Waiting)
  1223.                                 Size = Waiting;
  1224.  
  1225.                                 /* Are there any bytes to be transferred? */
  1226.  
  1227.                             if(Size)
  1228.                             {
  1229.                                     /* Read the data. */
  1230.  
  1231.                                 if(DoSerialRead(Buffer,Size))
  1232.                                 {
  1233.                                     if(SerialErrorReport(ReadRequest))
  1234.                                         return(-1);
  1235.                                     else
  1236.                                         Size = ReadRequest -> IOSer . io_Actual;
  1237.                                 }
  1238.  
  1239.                                 BytesIn += Size;
  1240.                             }
  1241.  
  1242.                             return(Size);
  1243.                         }
  1244.                     }
  1245.                 }
  1246.             }
  1247.         }
  1248.         else
  1249.             return(0);
  1250.     }
  1251.     else
  1252.         return(-1);
  1253. }
  1254.  
  1255.     /* xpr_swrite(APTR Buffer,LONG Size):
  1256.      *
  1257.      *    Write a few bytes to the serial port.
  1258.      */
  1259.  
  1260. LONG __saveds __asm
  1261. xpr_swrite(register __a0 APTR Buffer,register __d0 LONG Size)
  1262. {
  1263.     DB(kprintf("xpr_swrite(0x%08lx,%ld)\n",Buffer,Size));
  1264.  
  1265.     if(WriteRequest)
  1266.     {
  1267.             /* Return error if carrier is lost. */
  1268.  
  1269.         if(Config -> SerialConfig -> CheckCarrier && !Config -> SerialConfig -> DirectConnection)
  1270.         {
  1271.                 /* Is the carrier signal still present? */
  1272.  
  1273.             if(GetSerialStatus() & CIAF_COMCD)
  1274.             {
  1275.                 if(!CarrierMessage)
  1276.                 {
  1277.                     CarrierMessage = TRUE;
  1278.  
  1279.                     AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_CARRIER_LOST_TXT));
  1280.                 }
  1281.  
  1282.                 ObtainSemaphore(&OnlineSemaphore);
  1283.  
  1284.                 if(Online)
  1285.                 {
  1286.                     WasOnline    = Online;
  1287.                     Online        = FALSE;
  1288.                 }
  1289.  
  1290.                 ReleaseSemaphore(&OnlineSemaphore);
  1291.  
  1292.                 TransferError = TRUE;
  1293.  
  1294.                 return(-1);
  1295.             }
  1296.         }
  1297.  
  1298.             /* Send the data. */
  1299.  
  1300.         if(DoSerialWrite(Buffer,Size))
  1301.         {
  1302.             if(SerialErrorReport(WriteRequest))
  1303.                 return(-1);
  1304.         }
  1305.         else
  1306.             BytesOut += Size;
  1307.  
  1308.         return(0);
  1309.     }
  1310.     else
  1311.         return(-1);
  1312. }
  1313.  
  1314.     /* xpr_sflush():
  1315.      *
  1316.      *    Release the contents of all serial buffers.
  1317.      */
  1318.  
  1319. LONG __saveds __asm
  1320. xpr_sflush()
  1321. {
  1322.     DB(kprintf("xpr_sflush()\n"));
  1323.  
  1324.     return((LONG)DoSerialCmd(CMD_CLEAR));
  1325. }
  1326.  
  1327.     /* xpr_update(struct XPR_UPDATE *UpdateInfo):
  1328.      *
  1329.      *    Update the information displayed in the transfer window.
  1330.      */
  1331.  
  1332. LONG __saveds __asm
  1333. xpr_update(register __a0 struct XPR_UPDATE *UpdateInfo)
  1334. {
  1335.     DB(kprintf("xpr_update(0x%08lx)\n",UpdateInfo));
  1336.  
  1337.         /* No window available for output? */
  1338.  
  1339.     if(!TransferWindow)
  1340.     {
  1341.         if(!OpenTransferWindow())
  1342.             return(0);
  1343.     }
  1344.  
  1345.     if(UpdateInfo)
  1346.     {
  1347.         BYTE    NewByte = FALSE,
  1348.             NewTime = FALSE;
  1349.  
  1350.         if(TransferWindow -> Flags & WFLG_ZOOMED)
  1351.         {
  1352.             BOOLEAN Refresh;
  1353.  
  1354.             if(!TransferZoomed)
  1355.             {
  1356.                 ULONG Micros;
  1357.  
  1358.                 CurrentTime(&LastSeconds,&Micros);
  1359.  
  1360.                 Refresh = TRUE;
  1361.  
  1362.                 TransferZoomed = TRUE;
  1363.             }
  1364.             else
  1365.             {
  1366.                 ULONG Seconds,Micros;
  1367.  
  1368.                 CurrentTime(&Seconds,&Micros);
  1369.  
  1370.                 if(Seconds > LastSeconds)
  1371.                 {
  1372.                     LastSeconds = Seconds;
  1373.  
  1374.                     Refresh = TRUE;
  1375.                 }
  1376.             }
  1377.  
  1378.             if(Refresh)
  1379.             {
  1380.                 if(LastPercent > 0)
  1381.                     SPrintf(TransferTitleBuffer,"%s [%s %ld%%]",TransferWindowTitle,TruncateName(RealName),LastPercent);
  1382.                 else
  1383.                     SPrintf(TransferTitleBuffer,"%s [%s]",TransferWindowTitle,TruncateName(RealName));
  1384.  
  1385.                 SetWindowTitles(TransferWindow,TransferTitleBuffer,(STRPTR)-1);
  1386.             }
  1387.         }
  1388.         else
  1389.         {
  1390.             if(TransferZoomed)
  1391.             {
  1392.                 SetWindowTitles(TransferWindow,TransferWindowTitle,(STRPTR)-1);
  1393.  
  1394.                 TransferZoomed = FALSE;
  1395.             }
  1396.         }
  1397.  
  1398.         if((UpdateInfo -> xpru_updatemask & XPRU_PROTOCOL) && UpdateInfo -> xpru_protocol)
  1399.             LT_SetAttributes(TransferHandle,GAD_TRANSFER_PROTOCOL,GTTX_Text,UpdateInfo -> xpru_protocol,TAG_DONE);
  1400.  
  1401.         if((UpdateInfo -> xpru_updatemask & XPRU_MSG) && UpdateInfo -> xpru_msg)
  1402.             AddTransferInfo(FALSE,UpdateInfo -> xpru_msg);
  1403.  
  1404.         if((UpdateInfo -> xpru_updatemask & XPRU_ERRORMSG) && UpdateInfo -> xpru_errormsg)
  1405.             AddTransferInfo(TRUE,UpdateInfo -> xpru_errormsg);
  1406.  
  1407.         if((UpdateInfo -> xpru_updatemask & XPRU_FILENAME) && UpdateInfo -> xpru_filename)
  1408.         {
  1409.             STRPTR FileName = UpdateInfo -> xpru_filename;
  1410.  
  1411.             if(OriginalName[0])
  1412.             {
  1413.                 if(!Stricmp(ShrunkenName,FileName))
  1414.                     FileName = OriginalName;
  1415.             }
  1416.  
  1417.             FileName = NewFileName(FileName,RealName);
  1418.  
  1419.             LT_SetAttributes(TransferHandle,GAD_TRANSFER_FILE,LABX_Index,0,LABX_Text,TruncateName(FileName),TAG_DONE);
  1420.  
  1421.             if(FileTransferInfo)
  1422.             {
  1423.                 if(FileTransferInfo -> CurrentFile)
  1424.                 {
  1425.                     struct FileTransferNode *Node = (struct FileTransferNode *)FileTransferInfo -> CurrentFile -> Node . mln_Succ;
  1426.  
  1427.                     if(Node -> Node . mln_Succ)
  1428.                         LT_SetAttributes(TransferHandle,GAD_TRANSFER_FILE,LABX_Index,1,LABX_Text,TruncateName(Node -> Name),TAG_DONE);
  1429.                     else
  1430.                         LT_SetAttributes(TransferHandle,GAD_TRANSFER_FILE,LABX_Index,1,LABX_Text,LocaleString(MSG_GLOBAL_NONE_TXT),TAG_DONE);
  1431.                 }
  1432.  
  1433.                 PrintBox(GAD_TRANSFER_SIZE,2,ConvNumber,FileTransferInfo -> TotalSize);
  1434.  
  1435.                 if(FileTransferInfo -> TotalFiles)
  1436.                     PrintBox(GAD_TRANSFER_SIZE,4,LocaleString(MSG_TRANSFERPANEL_NUMBER_TO_GO_PERCENT_TXT),FileTransferInfo -> DoneFiles,FileTransferInfo -> TotalFiles,(100 * FileTransferInfo -> DoneFiles) / FileTransferInfo -> TotalFiles);
  1437.                 else
  1438.                     PrintBox(GAD_TRANSFER_SIZE,4,LocaleString(MSG_TRANSFERPANEL_NUMBER_TO_GO_PERCENT_TXT),FileTransferInfo -> DoneFiles,FileTransferInfo -> TotalFiles,0);
  1439.             }
  1440.         }
  1441.  
  1442.         if((UpdateInfo -> xpru_updatemask & XPRU_FILESIZE) && UpdateInfo -> xpru_filesize != -1)
  1443.         {
  1444.             if(CurrentFile)
  1445.             {
  1446.                 if(CurrentFile -> InfoPort)
  1447.                     PrintBox(GAD_TRANSFER_SIZE,0,ConvNumber10,UpdateInfo -> xpru_filesize);
  1448.                 else
  1449.                     PrintBox(GAD_TRANSFER_SIZE,0,ConvNumber,UpdateInfo -> xpru_filesize);
  1450.             }
  1451.             else
  1452.                 PrintBox(GAD_TRANSFER_SIZE,0,ConvNumber,UpdateInfo -> xpru_filesize);
  1453.  
  1454.             if(ByteMax = UpdateInfo -> xpru_filesize)
  1455.                 NewByte = TRUE;
  1456.         }
  1457.  
  1458.         if((UpdateInfo -> xpru_updatemask & XPRU_BYTES) && UpdateInfo -> xpru_bytes != -1)
  1459.         {
  1460.             if(CurrentFile)
  1461.             {
  1462.                 if(CurrentFile -> InfoPort)
  1463.                     PrintBox(GAD_TRANSFER_SIZE,1,ConvNumber10,ByteVal = UpdateInfo -> xpru_bytes);
  1464.                 else
  1465.                     PrintBox(GAD_TRANSFER_SIZE,1,ConvNumber,ByteVal = UpdateInfo -> xpru_bytes);
  1466.             }
  1467.             else
  1468.                 PrintBox(GAD_TRANSFER_SIZE,1,ConvNumber,ByteVal = UpdateInfo -> xpru_bytes);
  1469.  
  1470.             if(FileTransferInfo)
  1471.             {
  1472.                 ULONG Len = FileTransferInfo -> DoneSize + UpdateInfo -> xpru_bytes;
  1473.  
  1474.                 if(FileTransferInfo -> TotalSize)
  1475.                     PrintBox(GAD_TRANSFER_SIZE,3,LocaleString(MSG_TRANSFERPANEL_NUMBER_PERCENT_TXT),Len,(100 * Len) / FileTransferInfo -> TotalSize);
  1476.                 else
  1477.                     PrintBox(GAD_TRANSFER_SIZE,3,LocaleString(MSG_TRANSFERPANEL_NUMBER_PERCENT_TXT),Len,0);
  1478.             }
  1479.  
  1480.             if(ByteMax)
  1481.                 NewByte = TRUE;
  1482.  
  1483.             if(CurrentFile)
  1484.             {
  1485.                 if(CurrentFile -> InfoPort && !Uploading)
  1486.                 {
  1487.                     if(CurrentFile -> InfoData . id_NumBlocks && CurrentFile -> InfoData . id_BytesPerBlock)
  1488.                     {
  1489.                         if(ByteMax)
  1490.                         {
  1491.                             register LONG Space = CurrentFile -> InfoData . id_NumBlocks - CurrentFile -> InfoData . id_NumBlocksUsed;
  1492.  
  1493.                             if(Space >= 0)
  1494.                             {
  1495.                                     // Important! Only use the number of bytes still
  1496.                                     // to be transferred.
  1497.  
  1498.                                 register LONG Blocks = CalculateBlocks(ByteMax - ByteVal,CurrentFile -> InfoData . id_BytesPerBlock);
  1499.  
  1500.                                     // Did we take a look at the filing system yet?
  1501.  
  1502.                                 if(!TypeChecked)
  1503.                                 {
  1504.                                         // If this is not a block mapped device
  1505.                                         // we cannot guess what will happen if
  1506.                                         // it fills up (and whether it fills up at all).
  1507.  
  1508.                                     if(!IsBlockMappedDevice(CurrentFile -> InfoPort))
  1509.                                         DontWorry = TRUE;
  1510.  
  1511.                                         // Ok, done
  1512.  
  1513.                                     TypeChecked = TRUE;
  1514.                                 }
  1515.  
  1516.                                 if(Space >= Blocks || DontWorry)
  1517.                                     PrintBox(GAD_TRANSFER_FILE,2,LocaleString(MSG_TERMXPR_BYTES_FULL_TXT),Space * CurrentFile -> InfoData . id_BytesPerBlock,100 * (CurrentFile -> InfoData . id_NumBlocksUsed) / CurrentFile -> InfoData . id_NumBlocks,"");
  1518.                                 else
  1519.                                 {
  1520.                                     if(!Alerted)
  1521.                                     {
  1522.                                         Alerted = TRUE;
  1523.  
  1524.                                         Say(LocaleString(MSG_TERMXPR_SAY_FILE_MAY_NOT_FIT_TXT));
  1525.                                     }
  1526.  
  1527.                                     PrintBox(GAD_TRANSFER_FILE,2,LocaleString(MSG_TERMXPR_BYTES_FULL_TXT),Space * CurrentFile -> InfoData . id_BytesPerBlock,100 * (CurrentFile -> InfoData . id_NumBlocksUsed) / CurrentFile -> InfoData . id_NumBlocks,LocaleString(MSG_TERMXPR_FILE_MAY_NOT_FIT_TXT));
  1528.                                 }
  1529.                             }
  1530.                             else
  1531.                                 PrintBox(GAD_TRANSFER_FILE,2,LocaleString(MSG_TERMXPR_BYTES_FULL_TXT),(CurrentFile -> InfoData . id_NumBlocks - CurrentFile -> InfoData . id_NumBlocksUsed) * CurrentFile -> InfoData . id_BytesPerBlock,100 * (CurrentFile -> InfoData . id_NumBlocksUsed) / CurrentFile -> InfoData . id_NumBlocks);
  1532.                         }
  1533.                         else
  1534.                             PrintBox(GAD_TRANSFER_FILE,2,LocaleString(MSG_TERMXPR_BYTES_FULL_TXT),(CurrentFile -> InfoData . id_NumBlocks - CurrentFile -> InfoData . id_NumBlocksUsed) * CurrentFile -> InfoData . id_BytesPerBlock,100 * (CurrentFile -> InfoData . id_NumBlocksUsed) / CurrentFile -> InfoData . id_NumBlocks);
  1535.                     }
  1536.                 }
  1537.             }
  1538.         }
  1539.  
  1540.         if((UpdateInfo -> xpru_updatemask & XPRU_BLOCKS) && UpdateInfo -> xpru_blocks != -1)
  1541.             PrintBox(GAD_TRANSFER_SIZE,5,ConvNumber,UpdateInfo -> xpru_blocks);
  1542.  
  1543.         if((UpdateInfo -> xpru_updatemask & XPRU_DATARATE) && UpdateInfo -> xpru_datarate > 0)
  1544.         {
  1545.             register LONG Change;
  1546.  
  1547.             CPS_Current = UpdateInfo -> xpru_datarate;
  1548.  
  1549.             if(CPS_Last)
  1550.             {
  1551.                 if(CPS_Last < UpdateInfo -> xpru_datarate)
  1552.                     Change = (100 * (UpdateInfo -> xpru_datarate - CPS_Last)) / CPS_Last;
  1553.                 else
  1554.                     Change = (100 * (CPS_Last - UpdateInfo -> xpru_datarate)) / CPS_Last;
  1555.             }
  1556.             else
  1557.                 Change = 100;
  1558.  
  1559.             if(Change > 1)
  1560.             {
  1561.                 PrintBox(GAD_TRANSFER_SECONDS,0,ConvNumber,UpdateInfo -> xpru_datarate);
  1562.  
  1563.                 CPS_Last = UpdateInfo -> xpru_datarate;
  1564.             }
  1565.  
  1566.             if(UpdateInfo -> xpru_datarate < CPS_Minimum)
  1567.                 CPS_Minimum = UpdateInfo -> xpru_datarate;
  1568.  
  1569.             if(UpdateInfo -> xpru_datarate > CPS_Maximum)
  1570.                 CPS_Maximum = UpdateInfo -> xpru_datarate;
  1571.  
  1572.             if((ULONG)(CPS_Average + UpdateInfo -> xpru_datarate) >= CPS_Average)
  1573.             {
  1574.                 CPS_Average += UpdateInfo -> xpru_datarate;
  1575.  
  1576.                 CPS_Count++;
  1577.             }
  1578.         }
  1579.  
  1580.         if((UpdateInfo -> xpru_updatemask & XPRU_CHARDELAY) && UpdateInfo -> xpru_chardelay != -1)
  1581.             PrintBox(GAD_TRANSFER_SECONDS,1,ConvNumber,UpdateInfo -> xpru_chardelay);
  1582.  
  1583.         if((UpdateInfo -> xpru_updatemask & XPRU_PACKETDELAY) && UpdateInfo -> xpru_packetdelay != -1)
  1584.             PrintBox(GAD_TRANSFER_SECONDS,2,ConvNumber,UpdateInfo -> xpru_packetdelay);
  1585.  
  1586.         if((UpdateInfo -> xpru_updatemask & XPRU_PACKETTYPE) && UpdateInfo -> xpru_packettype != -1)
  1587.         {
  1588.             if(UpdateInfo -> xpru_packettype > 32 && UpdateInfo -> xpru_packettype < 256)
  1589.             {
  1590.                 if(IsPrintable[UpdateInfo -> xpru_packettype])
  1591.                     PrintBox(GAD_TRANSFER_SECONDS,3,"`%lc'",UpdateInfo -> xpru_packettype);
  1592.                 else
  1593.                     PrintBox(GAD_TRANSFER_SECONDS,3,ConvNumber,UpdateInfo -> xpru_packettype);
  1594.             }
  1595.             else
  1596.                 PrintBox(GAD_TRANSFER_SECONDS,3,ConvNumber,UpdateInfo -> xpru_packettype);
  1597.         }
  1598.  
  1599.         if((UpdateInfo -> xpru_updatemask & XPRU_BLOCKCHECK) && UpdateInfo -> xpru_blockcheck)
  1600.             PrintBox(GAD_TRANSFER_SECONDS,4,UpdateInfo -> xpru_blockcheck);
  1601.  
  1602.         if((UpdateInfo -> xpru_updatemask & XPRU_BLOCKSIZE) && UpdateInfo -> xpru_blocksize != -1)
  1603.             PrintBox(GAD_TRANSFER_SECONDS,5,ConvNumber,UpdateInfo -> xpru_blocksize);
  1604.  
  1605.  
  1606.         if((UpdateInfo -> xpru_updatemask & XPRU_EXPECTTIME) && UpdateInfo -> xpru_expecttime)
  1607.         {
  1608.             PrintBox(GAD_TRANSFER_TOTALTIME,0,UpdateInfo -> xpru_expecttime);
  1609.  
  1610.             if(TimeMax = GetSeconds((STRPTR)UpdateInfo -> xpru_expecttime))
  1611.                 NewTime = TRUE;
  1612.         }
  1613.  
  1614.         if((UpdateInfo -> xpru_updatemask & XPRU_ELAPSEDTIME) && UpdateInfo -> xpru_elapsedtime)
  1615.         {
  1616.             PrintBox(GAD_TRANSFER_TOTALTIME,1,UpdateInfo -> xpru_elapsedtime);
  1617.  
  1618.             TimeVal = GetSeconds((STRPTR)UpdateInfo -> xpru_elapsedtime);
  1619.  
  1620.             if(TimeMax)
  1621.                 NewTime = TRUE;
  1622.         }
  1623.  
  1624.         if((UpdateInfo -> xpru_updatemask & XPRU_ERRORS) && UpdateInfo -> xpru_errors != -1)
  1625.         {
  1626.             PrintBox(GAD_TRANSFER_ERRORS,0,ConvNumber,UpdateInfo -> xpru_errors);
  1627.  
  1628.             if(!ErrorNotified && Config -> TransferConfig -> ErrorNotification && UpdateInfo -> xpru_errors >= Config -> TransferConfig -> ErrorNotification)
  1629.             {
  1630.                 ErrorNotified = TRUE;
  1631.  
  1632.                 WakeUp(TransferWindow,SOUND_ERROR);
  1633.             }
  1634.         }
  1635.  
  1636.         if((UpdateInfo -> xpru_updatemask & XPRU_TIMEOUTS) && UpdateInfo -> xpru_timeouts != -1)
  1637.             PrintBox(GAD_TRANSFER_ERRORS,1,ConvNumber,UpdateInfo -> xpru_timeouts);
  1638.  
  1639.         if(NewByte)
  1640.         {
  1641.             LONG Percent;
  1642.  
  1643.             if(ByteMax)
  1644.                 Percent = (100 * ByteVal) / ByteMax;
  1645.             else
  1646.                 Percent = 0;
  1647.  
  1648.             if(Percent != LastPercent)
  1649.             {
  1650.                 UBYTE LocalBuffer[10];
  1651.  
  1652.                 SPrintf(LocalBuffer,"%ld%%",Percent);
  1653.  
  1654.                 LastPercent = Percent;
  1655.  
  1656.                 LT_SetAttributes(TransferHandle,GAD_TRANSFER_PERCENT,
  1657.                     LAGA_Percent,    Percent,
  1658.                     LAGA_InfoText,    LocalBuffer,
  1659.                 TAG_DONE);
  1660.             }
  1661.         }
  1662.  
  1663.         if(NewTime)
  1664.         {
  1665.             register LONG TimeDif,Change;
  1666.  
  1667.             if(TimeVal > TimeMax)
  1668.                 TimeDif = 0;
  1669.             else
  1670.                 TimeDif = TimeMax - TimeVal;
  1671.  
  1672.             if(LastTimeDif)
  1673.             {
  1674.                 if(LastTimeDif < TimeDif)
  1675.                     Change = (100 * (TimeDif - LastTimeDif)) / LastTimeDif;
  1676.                 else
  1677.                     Change = (100 * (LastTimeDif - TimeDif)) / LastTimeDif;
  1678.             }
  1679.             else
  1680.                 Change = 100;
  1681.  
  1682.                 /* Don't update the display unless the change
  1683.                  * exceeds 2% of the previous value.
  1684.                  */
  1685.  
  1686.             if(Change > 2)
  1687.             {
  1688.                 UBYTE    LocalBuffer[10];
  1689.                 LONG    Percent;
  1690.  
  1691.                 LastTimeDif = TimeDif;
  1692.  
  1693.                 if(TimeMax)
  1694.                     Percent = (100 * TimeDif) / TimeMax;
  1695.                 else
  1696.                     Percent = 0;
  1697.  
  1698.                 SPrintf(LocalBuffer,"%2ld:%02ld:%02ld",TimeDif / 3600,(TimeDif / 60) % 60,TimeDif % 60);
  1699.  
  1700.                 LT_SetAttributes(TransferHandle,GAD_TRANSFER_TIME,
  1701.                     LAGA_Percent,    Percent,
  1702.                     LAGA_InfoText,    LocalBuffer,
  1703.                 TAG_DONE);
  1704.  
  1705.                     /* A rapidly changing transfer time display would
  1706.                      * cause the transfer completion time display to
  1707.                      * change at the same pace. As the completion time
  1708.                      * display calculation is rather costly, a change smaller
  1709.                      * than 5% of the previous value is silently ignored.
  1710.                      */
  1711.  
  1712.                 if(Change > 5)
  1713.                 {
  1714.                     UBYTE            DateTimeBuffer[256];
  1715.                     struct DateStamp    Stamp;
  1716.  
  1717.                         /* Obtain current time. */
  1718.  
  1719.                     DateStamp(&Stamp);
  1720.  
  1721.                         /* Add the time to go. */
  1722.  
  1723.                     Stamp . ds_Tick        += (TimeDif % 60) * TICKS_PER_SECOND;
  1724.                     Stamp . ds_Minute    += TimeDif / 60 + Stamp . ds_Tick / (60 * TICKS_PER_SECOND);
  1725.                     Stamp . ds_Days        += Stamp . ds_Minute / 1440;
  1726.  
  1727.                     Stamp . ds_Tick        %= 60 * TICKS_PER_SECOND;
  1728.                     Stamp . ds_Minute    %= 1440;
  1729.  
  1730.                         /* Conversion succeeded? */
  1731.  
  1732.                     if(FormatStamp(&Stamp,NULL,NULL,DateTimeBuffer,TRUE))
  1733.                         PrintBox(GAD_TRANSFER_FILE,3,DateTimeBuffer);
  1734.                 }
  1735.             }
  1736.         }
  1737.     }
  1738.  
  1739.     if(TransferPerfWindow)
  1740.     {
  1741.         struct RastPort *RPort = TransferPerfWindow -> RPort;
  1742.         LONG Height,Left,Top,Min,Avg,Cur;
  1743.  
  1744.         Left = TransferPerfWindow -> Width - (TransferPerfWindow -> BorderRight + 1);
  1745.         Height = TransferPerfWindow -> Height - (TransferPerfWindow -> BorderTop + TransferPerfWindow -> BorderBottom + 1);
  1746.         Top = TransferPerfWindow -> BorderTop + Height;
  1747.  
  1748.         if(CPS_Maximum && CPS_Maximum != ~0)
  1749.         {
  1750.             Min = (Height * CPS_Minimum) / CPS_Maximum;
  1751.             Cur = (Height * CPS_Current) / CPS_Maximum;
  1752.  
  1753.             if(CPS_Count)
  1754.                 Avg = ((CPS_Average / CPS_Count) * Height) / CPS_Maximum;
  1755.             else
  1756.                 Avg = 0;
  1757.         }
  1758.         else
  1759.             Min = Avg = Cur = 0;
  1760.  
  1761.         if(CPL_Min == -1)
  1762.             CPL_Min = Min;
  1763.  
  1764.         if(CPL_Avg == -1)
  1765.             CPL_Avg = Avg;
  1766.  
  1767.         if(CPL_Cur == -1)
  1768.             CPL_Cur = Cur;
  1769.  
  1770.         ScrollRaster(RPort,1,0,TransferPerfWindow -> BorderLeft,TransferPerfWindow -> BorderTop,TransferPerfWindow -> Width - (TransferPerfWindow -> BorderRight + 1),TransferPerfWindow -> Height - (TransferPerfWindow -> BorderBottom + 1));
  1771.  
  1772.         if(CPL_Cur != -1 && Cur != -1)
  1773.         {
  1774.             SetAPen(RPort,DrawInfo -> dri_Pens[SHADOWPEN]);
  1775.             Move(RPort,Left,Top - CPL_Cur);
  1776.             Draw(RPort,Left,Top - Cur);
  1777.         }
  1778.  
  1779.         if(CPL_Min != -1 && Min != -1)
  1780.         {
  1781.             SetAPen(RPort,DrawInfo -> dri_Pens[HIGHLIGHTTEXTPEN]);
  1782.             Move(RPort,Left,Top - CPL_Min);
  1783.             Draw(RPort,Left,Top - Min);
  1784.         }
  1785.  
  1786.         if(CPL_Avg != -1 && Avg != -1)
  1787.         {
  1788.             SetAPen(RPort,DrawInfo -> dri_Pens[FILLPEN]);
  1789.             Move(RPort,Left,Top - CPL_Avg);
  1790.             Draw(RPort,Left,Top - Avg);
  1791.         }
  1792.  
  1793.         CPL_Min = Min;
  1794.         CPL_Avg = Avg;
  1795.         CPL_Cur = Cur;
  1796.     }
  1797.  
  1798.     return(1);
  1799. }
  1800.  
  1801.     /* xpr_chkabort():
  1802.      *
  1803.      *    Check if the user has aborted the transfer.
  1804.      */
  1805.  
  1806. LONG __saveds __asm
  1807. xpr_chkabort()
  1808. {
  1809.     LONG Result;
  1810.  
  1811.     DB(kprintf("xpr_chkabort()\n"));
  1812.  
  1813.     if(TransferAbortState != 0)
  1814.     {
  1815.         Result = TransferAbortState;
  1816.  
  1817.         TransferAbortState = 0;
  1818.     }
  1819.     else
  1820.         Result = CheckAbort(Config -> SerialConfig -> CheckCarrier && !Config -> SerialConfig -> DirectConnection);
  1821.  
  1822.     return(Result);
  1823. }
  1824.  
  1825.     /* xpr_gets(STRPTR Prompt,STRPTR Buffer):
  1826.      *
  1827.      *    Prompt the user for string input.
  1828.      */
  1829.  
  1830. LONG __saveds __asm
  1831. xpr_gets(register __a0 STRPTR Prompt,register __a1 STRPTR Buffer)
  1832. {
  1833.     enum    {    GAD_OK=1,GAD_CANCEL,GAD_STRING };
  1834.  
  1835.     struct LayoutHandle    *Handle;
  1836.     LONG             Success = FALSE;
  1837.     UBYTE             LocalBuffer[256];
  1838.  
  1839.     DB(kprintf("xpr_gets(\"%s\",\"%s\")\n",Prompt,Buffer));
  1840.  
  1841.     if(strlen(Buffer) > 255)
  1842.     {
  1843.         CopyMem(Buffer,LocalBuffer,255);
  1844.  
  1845.         LocalBuffer[255] = 0;
  1846.     }
  1847.     else
  1848.         strcpy(LocalBuffer,Buffer);
  1849.  
  1850.     if(!Prompt)
  1851.         Prompt = LocaleString(MSG_TERMXPR_INPUT_REQUIRED_TXT);
  1852.  
  1853.     if(Handle = LT_CreateHandleTags(Window -> WScreen,
  1854.         LH_LocaleHook,    &LocaleHook,
  1855.     TAG_DONE))
  1856.     {
  1857.         struct Window *PanelWindow;
  1858.  
  1859.         LT_New(Handle,
  1860.             LA_Type,    VERTICAL_KIND,
  1861.         TAG_DONE);
  1862.         {
  1863.             LT_New(Handle,
  1864.                 LA_Type,    VERTICAL_KIND,
  1865.                 LA_LabelText,    Prompt,
  1866.             TAG_DONE);
  1867.             {
  1868.                 LT_New(Handle,
  1869.                     LA_Type,    STRING_KIND,
  1870.                     LA_STRPTR,    LocalBuffer,
  1871.                     LA_ID,        GAD_STRING,
  1872.                     LA_Chars,    30,
  1873.                 TAG_DONE);
  1874.  
  1875.                 LT_EndGroup(Handle);
  1876.             }
  1877.  
  1878.             LT_New(Handle,
  1879.                 LA_Type,VERTICAL_KIND,
  1880.             TAG_DONE);
  1881.             {
  1882.                 LT_New(Handle,
  1883.                     LA_Type,    XBAR_KIND,
  1884.                     LAXB_FullSize,    TRUE,
  1885.                 TAG_DONE);
  1886.  
  1887.                 LT_EndGroup(Handle);
  1888.             }
  1889.  
  1890.             LT_New(Handle,LA_Type,HORIZONTAL_KIND,
  1891.                 LAGR_SameSize,    TRUE,
  1892.                 LAGR_Spread,    TRUE,
  1893.             TAG_DONE);
  1894.             {
  1895.                 LT_New(Handle,
  1896.                     LA_Type,    BUTTON_KIND,
  1897.                     LA_LabelID,    MSG_TERMXPR_OKAY_GAD,
  1898.                     LA_ID,        GAD_OK,
  1899.                     LABT_ReturnKey,    TRUE,
  1900.                     LABT_ExtraFat,    TRUE,
  1901.                 TAG_DONE);
  1902.  
  1903.                 LT_New(Handle,
  1904.                     LA_Type,    BUTTON_KIND,
  1905.                     LA_LabelID,    MSG_GLOBAL_CANCEL_GAD,
  1906.                     LA_ID,        GAD_CANCEL,
  1907.                     LABT_EscKey,    TRUE,
  1908.                     LABT_ExtraFat,    TRUE,
  1909.                 TAG_DONE);
  1910.  
  1911.                 LT_EndGroup(Handle);
  1912.             }
  1913.         }
  1914.  
  1915.         if(PanelWindow = LT_Layout(Handle,LocaleString(MSG_GLOBAL_ENTER_TEXT_TXT),NULL,0,0,IDCMP_CLOSEWINDOW,0,
  1916.             LAWN_HelpHook,        &GuideHook,
  1917.             LAWN_Parent,        Window,
  1918.             WA_DepthGadget,        TRUE,
  1919.             WA_CloseGadget,        TRUE,
  1920.             WA_DragBar,        TRUE,
  1921.             WA_RMBTrap,        TRUE,
  1922.             WA_Activate,        TRUE,
  1923.         TAG_DONE))
  1924.         {
  1925.             struct IntuiMessage    *Message;
  1926.             BOOLEAN             Done = FALSE;
  1927.             ULONG             MsgClass,
  1928.                          MsgQualifier;
  1929.             UWORD             MsgCode;
  1930.             struct Gadget        *MsgGadget;
  1931.  
  1932.             PushWindow(PanelWindow);
  1933.  
  1934.             LT_ShowWindow(Handle,TRUE);
  1935.  
  1936.             LT_Activate(Handle,GAD_STRING);
  1937.  
  1938.             do
  1939.             {
  1940.                 if(Wait(PORTMASK(PanelWindow -> UserPort) | SIG_BREAK) & SIG_BREAK)
  1941.                     break;
  1942.  
  1943.                 while(Message = (struct IntuiMessage *)GT_GetIMsg(PanelWindow -> UserPort))
  1944.                 {
  1945.                     MsgClass    = Message -> Class;
  1946.                     MsgQualifier    = Message -> Qualifier;
  1947.                     MsgCode        = Message -> Code;
  1948.                     MsgGadget    = (struct Gadget *)Message -> IAddress;
  1949.  
  1950.                     GT_ReplyIMsg(Message);
  1951.  
  1952.                     LT_HandleInput(Handle,MsgQualifier,&MsgClass,&MsgCode,&MsgGadget);
  1953.  
  1954.                     if(MsgClass == IDCMP_CLOSEWINDOW)
  1955.                         Done = TRUE;
  1956.  
  1957.                     if(MsgClass == IDCMP_GADGETUP)
  1958.                     {
  1959.                         switch(MsgGadget -> GadgetID)
  1960.                         {
  1961.                             case GAD_STRING:
  1962.  
  1963.                                 if(MsgCode == '\r')
  1964.                                 {
  1965.                                     if(strcmp(Buffer,LocalBuffer))
  1966.                                         NewOptions = TRUE;
  1967.  
  1968.                                     strcpy(Buffer,LocalBuffer);
  1969.  
  1970.                                     Success = Done = TRUE;
  1971.  
  1972.                                     LT_PressButton(Handle,GAD_OK);
  1973.                                 }
  1974.  
  1975.                                 break;
  1976.  
  1977.                             case GAD_OK:
  1978.  
  1979.                                 LT_UpdateStrings(Handle);
  1980.  
  1981.                                 if(strcmp(Buffer,LocalBuffer))
  1982.                                     NewOptions = TRUE;
  1983.  
  1984.                                 strcpy(Buffer,LocalBuffer);
  1985.  
  1986.                                 Success = Done = TRUE;
  1987.  
  1988.                                 break;
  1989.  
  1990.                             case GAD_CANCEL:
  1991.  
  1992.                                 Done = TRUE;
  1993.                                 break;
  1994.                         }
  1995.                     }
  1996.                 }
  1997.             }
  1998.             while(!Done);
  1999.  
  2000.             PopWindow();
  2001.         }
  2002.  
  2003.         LT_DeleteHandle(Handle);
  2004.     }
  2005.  
  2006.     return(Success);
  2007. }
  2008.  
  2009.     /* xpr_setserial(LONG Status):
  2010.      *
  2011.      *    Set/read the serial status (parameters).
  2012.      */
  2013.  
  2014. LONG __saveds __asm
  2015. xpr_setserial(register __d0 LONG Status)
  2016. {
  2017.     DB(kprintf("xpr_setserial(0x%08lx)\n",Status));
  2018.  
  2019.     if(WriteRequest)
  2020.     {
  2021.         STATIC LONG XprBauds[12] =
  2022.         {
  2023.                110,
  2024.                300,
  2025.               1200,
  2026.               2400,
  2027.               4800,
  2028.               9600,
  2029.              19200,
  2030.              31250,
  2031.              38400,
  2032.              57600,
  2033.              76800,
  2034.             115200
  2035.         };
  2036.  
  2037.         LONG Return,i;
  2038.  
  2039.         StopSerialRead();
  2040.         StopSerialWrite();
  2041.  
  2042.         DoSerialCmd(SDCMD_QUERY);
  2043.  
  2044.         Return = WriteRequest -> io_SerFlags & 0xFF;
  2045.  
  2046.         if(WriteRequest -> io_ExtFlags & SEXTF_MSPON)
  2047.             Return |= ST_PARTYMARKON;
  2048.  
  2049.         if(WriteRequest -> io_ExtFlags & SEXTF_MARK)
  2050.             Return |= ST_PARTYMARK;
  2051.  
  2052.         if(WriteRequest -> io_StopBits == 2)
  2053.             Return |= ST_2BITS;
  2054.  
  2055.         if(WriteRequest -> io_ReadLen == 7)
  2056.             Return |= ST_READ7;
  2057.  
  2058.         if(WriteRequest -> io_WriteLen == 7)
  2059.             Return |= ST_WRITE7;
  2060.  
  2061.         for(i = 0 ; i < 12 ; i++)
  2062.         {
  2063.             if(XprBauds[i] >= WriteRequest -> io_Baud)
  2064.             {
  2065.                 Return |= (i << 16);
  2066.  
  2067.                 break;
  2068.             }
  2069.         }
  2070.  
  2071.             /* Update serial parameters, don't change
  2072.              * the baud rate however.
  2073.              */
  2074.  
  2075.         if(Status != -1)
  2076.         {
  2077.             WriteRequest -> io_SerFlags = Status & 0xFF;
  2078.             WriteRequest -> io_ExtFlags = 0;
  2079.  
  2080.             if(Status & ST_PARTYMARKON)
  2081.                 WriteRequest -> io_ExtFlags |= SEXTF_MSPON;
  2082.  
  2083.             if(Status & ST_PARTYMARK)
  2084.                 WriteRequest -> io_ExtFlags |= SEXTF_MARK;
  2085.  
  2086.             if(Status & ST_2BITS)
  2087.                 WriteRequest -> io_StopBits = 2;
  2088.             else
  2089.                 WriteRequest -> io_StopBits = 1;
  2090.  
  2091.             if(Status & ST_READ7)
  2092.                 WriteRequest -> io_ReadLen = 7;
  2093.             else
  2094.                 WriteRequest -> io_ReadLen = 8;
  2095.  
  2096.             if(Status & ST_WRITE7)
  2097.                 WriteRequest -> io_WriteLen = 7;
  2098.             else
  2099.                 WriteRequest -> io_WriteLen = 8;
  2100.  
  2101.             WriteRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
  2102.  
  2103.             DoIO(WriteRequest);
  2104.  
  2105.             CopyMem(WriteRequest,ReadRequest,sizeof(struct IOExtSer));
  2106.  
  2107.             ReadRequest -> IOSer . io_Message . mn_ReplyPort = ReadPort;
  2108.  
  2109.             CopyWriteFlags();
  2110.  
  2111.             if(WriteRequest -> io_SerFlags & SERF_7WIRE)
  2112.             {
  2113.                 if(Config -> SerialConfig -> HandshakingProtocol == HANDSHAKING_NONE)
  2114.                     Config -> SerialConfig -> HandshakingProtocol = HANDSHAKING_RTSCTS_DSR;
  2115.             }
  2116.             else
  2117.             {
  2118.                 if(Config -> SerialConfig -> HandshakingProtocol != HANDSHAKING_NONE)
  2119.                     Config -> SerialConfig -> HandshakingProtocol = HANDSHAKING_NONE;
  2120.             }
  2121.         }
  2122.  
  2123.         return(Return);
  2124.     }
  2125.     else
  2126.         return(-1);
  2127. }
  2128.  
  2129.     /* xpr_ffirst(STRPTR Buffer,STRPTR Pattern):
  2130.      *
  2131.      *    Batch file upload: find the first matching file and return
  2132.      *    its name.
  2133.      */
  2134.  
  2135. LONG __saveds __asm
  2136. xpr_ffirst(register __a0 STRPTR Buffer,register __a1 STRPTR Pattern)
  2137. {
  2138.     DB(kprintf("xpr_ffirst(0x%08lx,\"%s\")\n",Buffer,Pattern));
  2139.  
  2140.     if(FileTransferInfo)
  2141.     {
  2142.         FileTransferInfo -> DoneSize    = 0;
  2143.         FileTransferInfo -> DoneFiles    = 0;
  2144.  
  2145.         FileTransferInfo -> CurrentFile    = (struct FileTransferNode *)FileTransferInfo -> FileList . mlh_Head;
  2146.         FileTransferInfo -> CurrentSize    = FileTransferInfo -> CurrentFile -> Size;
  2147.  
  2148.         if(Config -> TransferConfig -> MangleFileNames)
  2149.         {
  2150.             UBYTE LocalName[MAX_FILENAME_LENGTH],*Char;
  2151.  
  2152.             strcpy(OriginalName,FileTransferInfo -> CurrentFile -> Name);
  2153.  
  2154.             ShrinkName(FilePart(FileTransferInfo -> CurrentFile -> Name),LocalName,12,TRUE);
  2155.  
  2156.             strcpy(Buffer,FileTransferInfo -> CurrentFile -> Name);
  2157.  
  2158.             Char = PathPart(Buffer);
  2159.  
  2160.             *Char = 0;
  2161.  
  2162.             AddPart(Buffer,LocalName,MAX_FILENAME_LENGTH);
  2163.  
  2164.             strcpy(ShrunkenName,Buffer);
  2165.         }
  2166.         else
  2167.         {
  2168.             OriginalName[0] = 0;
  2169.  
  2170.             strcpy(Buffer,FileTransferInfo -> CurrentFile -> Name);
  2171.         }
  2172.  
  2173.         return(1);
  2174.     }
  2175.     else
  2176.         return(0);
  2177. }
  2178.  
  2179.     /* xpr_fnext(LONG OldState,STRPTR Buffer,STRPTR Pattern):
  2180.      *
  2181.      *    Batch file upload: find the next matching file
  2182.      *    - if any - and return its name.
  2183.      */
  2184.  
  2185. LONG __saveds __asm
  2186. xpr_fnext(register __d0 LONG OldState,register __a0 STRPTR Buffer,register __a1 STRPTR Pattern)
  2187. {
  2188.     DB(kprintf("xpr_fnext(%ld,0x%08lx,\"%s\")\n",OldState,Buffer,Pattern));
  2189.  
  2190.     if(FileTransferInfo)
  2191.     {
  2192.         if(FileTransferInfo -> CurrentFile -> Node . mln_Succ -> mln_Succ)
  2193.         {
  2194.             FileTransferInfo -> DoneSize    += FileTransferInfo -> CurrentSize;
  2195.             FileTransferInfo -> DoneFiles    += 1;
  2196.  
  2197.             FileTransferInfo -> CurrentFile  = (struct FileTransferNode *)FileTransferInfo -> CurrentFile -> Node . mln_Succ;
  2198.             FileTransferInfo -> CurrentSize  = FileTransferInfo -> CurrentFile -> Size;
  2199.  
  2200.             if(Config -> TransferConfig -> MangleFileNames)
  2201.             {
  2202.                 UBYTE LocalName[MAX_FILENAME_LENGTH],*Char;
  2203.  
  2204.                 strcpy(OriginalName,FileTransferInfo -> CurrentFile -> Name);
  2205.  
  2206.                 ShrinkName(FilePart(FileTransferInfo -> CurrentFile -> Name),LocalName,12,TRUE);
  2207.  
  2208.                 strcpy(Buffer,FileTransferInfo -> CurrentFile -> Name);
  2209.  
  2210.                 Char = PathPart(Buffer);
  2211.  
  2212.                 *Char = 0;
  2213.  
  2214.                 AddPart(Buffer,LocalName,MAX_FILENAME_LENGTH);
  2215.  
  2216.                 strcpy(ShrunkenName,Buffer);
  2217.             }
  2218.             else
  2219.             {
  2220.                 OriginalName[0] = 0;
  2221.  
  2222.                 strcpy(Buffer,FileTransferInfo -> CurrentFile -> Name);
  2223.             }
  2224.  
  2225.             return(1);
  2226.         }
  2227.     }
  2228.  
  2229.     return(0);
  2230. }
  2231.  
  2232.     /* xpr_finfo(STRPTR FileName,LONG InfoType):
  2233.      *
  2234.      *    Return information on a given file.
  2235.      */
  2236.  
  2237. LONG __saveds __asm
  2238. xpr_finfo(register __a0 STRPTR FileName,register __d0 LONG InfoType)
  2239. {
  2240.     struct FileInfoBlock    *FileInfo;
  2241.     LONG             Size;
  2242.  
  2243.     DB(kprintf("xpr_finfo(\"%s\",%ld)\n",FileName,InfoType));
  2244.  
  2245.     switch(InfoType)
  2246.     {
  2247.             /* Return the file size. */
  2248.  
  2249.         case 1:    Size = 0;
  2250.  
  2251.             if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
  2252.             {
  2253.                 UBYTE    RealName[MAX_FILENAME_LENGTH];
  2254.                 BPTR    FileLock;
  2255.  
  2256.                 if(OriginalName[0])
  2257.                 {
  2258.                     if(!Stricmp(ShrunkenName,FileName))
  2259.                         FileName = NewFileName(OriginalName,RealName);
  2260.                     else
  2261.                         FileName = NewFileName(FileName,RealName);
  2262.                 }
  2263.                 else
  2264.                     FileName = NewFileName(FileName,RealName);
  2265.  
  2266.                 if(FileLock = Lock(FileName,ACCESS_READ))
  2267.                 {
  2268.                     if(Examine(FileLock,FileInfo))
  2269.                     {
  2270.                         if(FileInfo -> fib_DirEntryType < 0)
  2271.                             Size = FileInfo -> fib_Size;
  2272.                     }
  2273.  
  2274.                     UnLock(FileLock);
  2275.                 }
  2276.  
  2277.                 FreeDosObject(DOS_FIB,FileInfo);
  2278.             }
  2279.  
  2280.             return(Size);
  2281.  
  2282.             /* Return the file transfer mode. */
  2283.  
  2284.         case 2:    return(BinaryTransfer ? 1 : 2);
  2285.  
  2286.             /* Ignore the rest. */
  2287.  
  2288.         default:return(0);
  2289.     }
  2290. }
  2291.  
  2292.     /* xpr_options(LONG NumOpts,struct xpr_option **Opts):
  2293.      *
  2294.      *    Provide a more polished user interface to set the
  2295.      *    transfer protocol options.
  2296.      */
  2297.  
  2298. ULONG __saveds __asm
  2299. xpr_options(register __d0 LONG NumOpts,register __a0 struct xpr_option **Opts)
  2300. {
  2301.     DB(kprintf("xpr_options(%ld,0x%08lx)\n",NumOpts,Opts));
  2302.  
  2303.     if(NumOpts && Opts)
  2304.     {
  2305.         enum    {    GAD_USE=1,GAD_CANCEL,GAD_SPECIAL };
  2306.  
  2307.         struct LayoutHandle    *Handle;
  2308.         ULONG             Flags = NULL;
  2309.  
  2310.             /* We only have 32 bits! */
  2311.  
  2312.         if(NumOpts > 32)
  2313.             NumOpts = 32;
  2314.  
  2315.         if(Handle = LT_CreateHandleTags(Window -> WScreen,
  2316.             LH_LocaleHook,    &LocaleHook,
  2317.         TAG_DONE))
  2318.         {
  2319.             struct Window    *PanelWindow;
  2320.             LONG         i,Split;
  2321.  
  2322.             if(NumOpts > 16)
  2323.                 Split = NumOpts / 2;
  2324.             else
  2325.                 Split = -1;
  2326.  
  2327.             LT_New(Handle,
  2328.                 LA_Type,    VERTICAL_KIND,
  2329.             TAG_DONE);
  2330.             {
  2331.                 LT_New(Handle,
  2332.                     LA_Type,    HORIZONTAL_KIND,
  2333.                     LA_LabelID,    MSG_V36_1501,
  2334.                 TAG_DONE);
  2335.                 {
  2336.                     LT_New(Handle,
  2337.                         LA_Type,    VERTICAL_KIND,
  2338.                     TAG_DONE);
  2339.                     {
  2340.                         for(i = 0 ; i < NumOpts ; i++)
  2341.                         {
  2342.                             if(Opts[i])
  2343.                             {
  2344.                                 switch(Opts[i] -> xpro_type)
  2345.                                 {
  2346.                                     case XPRO_BOOLEAN:
  2347.  
  2348.                                         LT_New(Handle,
  2349.                                             LA_Type,    CHECKBOX_KIND,
  2350.                                             LA_LabelText,    Opts[i] -> xpro_description,
  2351.                                             LA_ID,        GAD_SPECIAL + i,
  2352.                                             GTCB_Checked,    GetOptionMode(Opts[i]),
  2353.                                         TAG_DONE);
  2354.  
  2355.                                         break;
  2356.  
  2357.                                     case XPRO_LONG:
  2358.  
  2359.                                         LT_New(Handle,
  2360.                                             LA_Type,        INTEGER_KIND,
  2361.                                             LA_LabelText,        Opts[i] -> xpro_description,
  2362.                                             LA_ID,            GAD_SPECIAL + i,
  2363.                                             LA_Chars,        15,
  2364.                                             GTIN_Number,        Atol(Opts[i] -> xpro_value),
  2365.                                             LAIN_UseIncrementers,    TRUE,
  2366.                                         TAG_DONE);
  2367.  
  2368.                                         break;
  2369.  
  2370.                                     case XPRO_STRING:
  2371.  
  2372.                                         LT_New(Handle,
  2373.                                             LA_Type,    STRING_KIND,
  2374.                                             LA_LabelText,    Opts[i] -> xpro_description,
  2375.                                             LA_ID,        GAD_SPECIAL + i,
  2376.                                             LA_Chars,    15,
  2377.                                             GTST_String,    Opts[i] -> xpro_value,
  2378.                                             GTST_MaxChars,    Opts[i] -> xpro_length - 1,
  2379.                                         TAG_DONE);
  2380.  
  2381.                                         break;
  2382.  
  2383.                                     case XPRO_COMMPAR:
  2384.  
  2385.                                         LT_New(Handle,
  2386.                                             LA_Type,    STRING_KIND,
  2387.                                             LA_LabelText,    Opts[i] -> xpro_description,
  2388.                                             LA_ID,        GAD_SPECIAL + i,
  2389.                                             LA_Chars,    15,
  2390.                                             LA_HighLabel,    TRUE,
  2391.                                             GTST_String,    Opts[i] -> xpro_value,
  2392.                                             GTST_MaxChars,    Opts[i] -> xpro_length - 1,
  2393.                                         TAG_DONE);
  2394.  
  2395.                                         break;
  2396.  
  2397.                                     case XPRO_HEADER:
  2398.  
  2399.                                         LT_New(Handle,
  2400.                                             LA_Type,    TEXT_KIND,
  2401.                                             LA_LabelText,    Opts[i] -> xpro_description,
  2402.                                             LA_HighLabel,    TRUE,
  2403.                                             GTTX_Text,    " ",
  2404.                                         TAG_DONE);
  2405.  
  2406.                                         break;
  2407.  
  2408.                                     case XPRO_COMMAND:
  2409.  
  2410.                                         LT_New(Handle,
  2411.                                             LA_Type,    BUTTON_KIND,
  2412.                                             LA_LabelText,    Opts[i] -> xpro_description,
  2413.                                             LA_ID,        GAD_SPECIAL + i,
  2414.                                             LA_Chars,    15,
  2415.                                         TAG_DONE);
  2416.  
  2417.                                         break;
  2418.                                 }
  2419.                             }
  2420.  
  2421.                             if(i == Split)
  2422.                             {
  2423.                                 LT_EndGroup(Handle);
  2424.  
  2425.                                 LT_New(Handle,
  2426.                                     LA_Type,    VERTICAL_KIND,
  2427.                                 TAG_DONE);
  2428.                             }
  2429.                         }
  2430.  
  2431.                         LT_EndGroup(Handle);
  2432.                     }
  2433.  
  2434.                     LT_EndGroup(Handle);
  2435.                 }
  2436.  
  2437.                 LT_New(Handle,
  2438.                     LA_Type,VERTICAL_KIND,
  2439.                 TAG_DONE);
  2440.                 {
  2441.                     LT_New(Handle,
  2442.                         LA_Type,    XBAR_KIND,
  2443.                         LAXB_FullSize,    TRUE,
  2444.                     TAG_DONE);
  2445.  
  2446.                     LT_EndGroup(Handle);
  2447.                 }
  2448.  
  2449.                 LT_New(Handle,LA_Type,HORIZONTAL_KIND,
  2450.                     LAGR_SameSize,    TRUE,
  2451.                     LAGR_Spread,    TRUE,
  2452.                 TAG_DONE);
  2453.                 {
  2454.                     LT_New(Handle,
  2455.                         LA_Type,    BUTTON_KIND,
  2456.                         LA_LabelID,    MSG_GLOBAL_USE_GAD,
  2457.                         LA_ID,        GAD_USE,
  2458.                         LABT_ReturnKey,    TRUE,
  2459.                         LABT_ExtraFat,    TRUE,
  2460.                     TAG_DONE);
  2461.  
  2462.                     LT_New(Handle,
  2463.                         LA_Type,    BUTTON_KIND,
  2464.                         LA_LabelID,    MSG_GLOBAL_CANCEL_GAD,
  2465.                         LA_ID,        GAD_CANCEL,
  2466.                         LABT_EscKey,    TRUE,
  2467.                         LABT_ExtraFat,    TRUE,
  2468.                     TAG_DONE);
  2469.  
  2470.                     LT_EndGroup(Handle);
  2471.                 }
  2472.  
  2473.                 LT_EndGroup(Handle);
  2474.             }
  2475.  
  2476.             if(PanelWindow = LT_Layout(Handle,OptionTitle ? OptionTitle : LocaleString(MSG_TERMXPR_TRANSFER_OPTIONS_TXT),NULL,0,0,IDCMP_CLOSEWINDOW,0,
  2477.                 LAWN_HelpHook,        &GuideHook,
  2478.                 LAWN_Parent,        Window,
  2479.                 WA_DepthGadget,        TRUE,
  2480.                 WA_CloseGadget,        TRUE,
  2481.                 WA_DragBar,        TRUE,
  2482.                 WA_RMBTrap,        TRUE,
  2483.                 WA_Activate,        TRUE,
  2484.             TAG_DONE))
  2485.             {
  2486.                 struct IntuiMessage    *Message;
  2487.                 BOOLEAN             Done = FALSE;
  2488.                 ULONG             MsgClass,
  2489.                              MsgQualifier;
  2490.                 UWORD             MsgCode;
  2491.                 struct Gadget        *MsgGadget;
  2492.                 BOOLEAN             CheckFlags = FALSE;
  2493.  
  2494.                 PushWindow(PanelWindow);
  2495.  
  2496.                 LT_ShowWindow(Handle,TRUE);
  2497.  
  2498.                 do
  2499.                 {
  2500.                     if(Wait(PORTMASK(PanelWindow -> UserPort) | SIG_BREAK) & SIG_BREAK)
  2501.                         break;
  2502.  
  2503.                     while(Message = (struct IntuiMessage *)GT_GetIMsg(PanelWindow -> UserPort))
  2504.                     {
  2505.                         MsgClass    = Message -> Class;
  2506.                         MsgQualifier    = Message -> Qualifier;
  2507.                         MsgCode        = Message -> Code;
  2508.                         MsgGadget    = (struct Gadget *)Message -> IAddress;
  2509.  
  2510.                         GT_ReplyIMsg(Message);
  2511.  
  2512.                         LT_HandleInput(Handle,MsgQualifier,&MsgClass,&MsgCode,&MsgGadget);
  2513.  
  2514.                         if(MsgClass == IDCMP_CLOSEWINDOW)
  2515.                             Done = TRUE;
  2516.  
  2517.                         if(MsgClass == IDCMP_GADGETUP)
  2518.                         {
  2519.                             switch(MsgGadget -> GadgetID)
  2520.                             {
  2521.                                 case GAD_USE:
  2522.  
  2523.                                     Done = CheckFlags = TRUE;
  2524.                                     break;
  2525.  
  2526.                                 case GAD_CANCEL:
  2527.  
  2528.                                     Done = TRUE;
  2529.                                     break;
  2530.  
  2531.                                 default:
  2532.  
  2533.                                     if(MsgGadget -> GadgetID - GAD_SPECIAL < NumOpts)
  2534.                                     {
  2535.                                         i = MsgGadget -> GadgetID - GAD_SPECIAL;
  2536.  
  2537.                                         if(Opts[i] -> xpro_type == XPRO_COMMAND || (Opts[i] -> xpro_type == XPRO_COMMPAR && MsgCode != '\t'))
  2538.                                         {
  2539.                                             Flags = (1L << i);
  2540.  
  2541.                                             XPRCommandSelected = Done = CheckFlags = TRUE;
  2542.                                         }
  2543.                                     }
  2544.  
  2545.                                     break;
  2546.                             }
  2547.                         }
  2548.                     }
  2549.                 }
  2550.                 while(!Done);
  2551.  
  2552.                 PopWindow();
  2553.  
  2554.                 if(CheckFlags)
  2555.                 {
  2556.                     LT_LockWindow(PanelWindow);
  2557.  
  2558.                     for(i = 0 ; i < NumOpts ; i++)
  2559.                     {
  2560.                         if(Opts[i])
  2561.                         {
  2562.                             switch(Opts[i] -> xpro_type)
  2563.                             {
  2564.                                 case XPRO_BOOLEAN:
  2565.  
  2566.                                     if(LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE) != GetOptionMode(Opts[i]))
  2567.                                     {
  2568.                                         Flags |= (1L << i);
  2569.  
  2570.                                         if(LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE))
  2571.                                             strcpy(Opts[i] -> xpro_value,"yes");
  2572.                                         else
  2573.                                             strcpy(Opts[i] -> xpro_value,"no");
  2574.  
  2575.                                         NewOptions = TRUE;
  2576.                                     }
  2577.  
  2578.                                     break;
  2579.  
  2580.                                 case XPRO_LONG:
  2581.  
  2582.                                     if(Atol(Opts[i] -> xpro_value) != LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE))
  2583.                                     {
  2584.                                         Flags |= (1L << i);
  2585.  
  2586.                                         SPrintf(Opts[i] -> xpro_value,"%ld",LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE));
  2587.  
  2588.                                         NewOptions = TRUE;
  2589.                                     }
  2590.  
  2591.                                     break;
  2592.  
  2593.                                 case XPRO_STRING:
  2594.  
  2595.                                     if(strcmp(Opts[i] -> xpro_value,(STRPTR)LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE)))
  2596.                                     {
  2597.                                         Flags |= (1L << i);
  2598.  
  2599.                                         strcpy(Opts[i] -> xpro_value,(STRPTR)LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE));
  2600.  
  2601.                                         NewOptions = TRUE;
  2602.                                     }
  2603.  
  2604.                                     break;
  2605.                             }
  2606.                         }
  2607.                     }
  2608.  
  2609.                     LT_UnlockWindow(PanelWindow);
  2610.                 }
  2611.                 else
  2612.                     Flags = NULL;
  2613.             }
  2614.  
  2615.             LT_DeleteHandle(Handle);
  2616.         }
  2617.  
  2618.         return(Flags);
  2619.     }
  2620.     else
  2621.         return(NULL);
  2622. }
  2623.  
  2624.     /* xpr_unlink(STRPTR FileName):
  2625.      *
  2626.      *    Remove (delete) a given file.
  2627.      */
  2628.  
  2629. LONG __saveds __asm
  2630. xpr_unlink(register __a0 STRPTR FileName)
  2631. {
  2632.     DB(kprintf("xpr_unlink(\"%s\")\n",FileName));
  2633.  
  2634.         /* Sorry, but it is far too dangerous to let the protocol
  2635.          * remove any files with path name substitution enabled.
  2636.          * The protocol could accidentally hit the wrong file.
  2637.          */
  2638.  
  2639.     if(!Config -> TransferConfig -> OverridePath)
  2640.     {
  2641.         if(OriginalName[0])
  2642.         {
  2643.             if(!Stricmp(ShrunkenName,FileName))
  2644.                 FileName = OriginalName;
  2645.         }
  2646.  
  2647.         if(DeleteFile(FileName))
  2648.         {
  2649.             LogAction(LocaleString(MSG_TERMXPR_LOGMSG_DELETE_FILE_TXT),FilePart(FileName));
  2650.  
  2651.             return(0);
  2652.         }
  2653.     }
  2654.  
  2655.     return(-1);
  2656. }
  2657.  
  2658.     /* xpr_squery():
  2659.      *
  2660.      *    Check how many characters are present in the serial buffer.
  2661.      */
  2662.  
  2663. LONG __saveds __asm
  2664. xpr_squery()
  2665. {
  2666.     DB(kprintf("xpr_squery()\n"));
  2667.  
  2668.     if(WriteRequest)
  2669.     {
  2670.         ULONG    Waiting;
  2671.         UWORD    Status;
  2672.  
  2673.         GetSerialInfo(&Waiting,&Status);
  2674.  
  2675.             /* Return error if carrier is lost. */
  2676.  
  2677.         if((Status & CIAF_COMCD) && Config -> SerialConfig -> CheckCarrier && !Config -> SerialConfig -> DirectConnection)
  2678.         {
  2679.             if(!CarrierMessage)
  2680.             {
  2681.                 CarrierMessage = TRUE;
  2682.  
  2683.                 AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_CARRIER_LOST_TXT));
  2684.             }
  2685.  
  2686.             ObtainSemaphore(&OnlineSemaphore);
  2687.  
  2688.             if(Online)
  2689.             {
  2690.                 WasOnline    = Online;
  2691.                 Online        = FALSE;
  2692.             }
  2693.  
  2694.             ReleaseSemaphore(&OnlineSemaphore);
  2695.  
  2696.             TransferError = TRUE;
  2697.         }
  2698.         else
  2699.             return((LONG)Waiting);
  2700.     }
  2701.  
  2702.     return(-1);
  2703. }
  2704.  
  2705.     /* xpr_getptr(LONG InfoType):
  2706.      *
  2707.      *    Return a pointer to the term custom screen.
  2708.      */
  2709.  
  2710. LONG __saveds __asm
  2711. xpr_getptr(register __d0 LONG InfoType)
  2712. {
  2713.     DB(kprintf("xpr_getptr(%ld)\n",InfoType));
  2714.  
  2715.     if(InfoType == 1)
  2716.         return((LONG)Window -> WScreen);
  2717.     else
  2718.         return(-1);
  2719. }
  2720.  
  2721.     /* xpr_stealopts(STRPTR Prompt,STRPTR Buffer):
  2722.      *
  2723.      *    Steal the contents of the options buffer (replacement
  2724.      *    for xpr_gets).
  2725.      */
  2726.  
  2727. LONG __saveds __asm
  2728. xpr_stealopts(register __a0 STRPTR Prompt,register __a1 STRPTR Buffer)
  2729. {
  2730.     DB(kprintf("xpr_stealopts(\"%s\",\"%s\")\n",Prompt,Buffer));
  2731.  
  2732.     if(Buffer)
  2733.         strcpy(ProtocolOptsBuffer,Buffer);
  2734.  
  2735.     return(1);
  2736. }
  2737.